lindsay@stobhill.newcastle.ac.uk (Lindsay F. Marshall) (11/28/89)
I have an application that worked under the 1.2 rules but wil not compile under 2.0. This seems to be to a considerable tightening of the rules for protected members. What I am not sure is whether or not it is correct!! The situation class A { protected:: A(); ~A(); void* data; }; class B : public A { public: B(); ~B(); A* next; }; So B is derived from and A and an instance of class B can access the field data without problems. However, if the class B uses an instance of class A inside one of its members, for example: B::~B() { while (next != this) { delete next; } } The compiler will not permit this access saying that the destructor is protected. The same thing happens if one tries to access next->data. Is this correct or is the compiler being too strict? If it's correct is there any point in having a protected, non-virtual destructor - it might as well be private. This happens with both C++ 2.0 and g++ 1.36.1 . Lindsay -- MAIL : Lindsay.Marshall@newcastle.ac.uk (UUCP: s/\(.*\)/...!ukc!\1/) POST : Computing Laboratory, The University, Newcastle upon Tyne, UK NE1 7RU VOICE: +44-91-222-8267 FAX: +44-91-222-8232
peter@mit-amt.MEDIA.MIT.EDU (Peter Schroeder) (11/29/89)
In article lindsay@stobhill.newcastle.ac.uk (Lindsay F. Marshall) writes: class A { protected:: A(); ~A(); void* data; }; class B : public A { public: B(); ~B(); A* next; }; B::~B() { while (next != this) { delete next; } } >The compiler will not permit this access saying that the destructor is >protected. The same thing happens if one tries to access next->data. >Is this correct or is the compiler being too strict? This is correct. As a member of B, A* is just some class and can only be accessed as allowed by the original class definition. If we defined a class D which looks exactly like class A and then replaced the occurence of A* in B by D* it would be clear that we cannot expect to be able to access D's desctructor. I stumbled over this a few times, since 1.2.1 of cfront did not seem to enforce it, but I can now see that it makes sense to forbid this. Hope this helps. Peter peter@media-lab.media.mit.edu
sakkinen@tukki.jyu.fi (Markku Sakkinen) (11/30/89)
In article lindsay@stobhill.newcastle.ac.uk (Lindsay F. Marshall) writes: -I have an application that worked under the 1.2 rules but wil not -compile under 2.0. This seems to be to a considerable tightening of -the rules for protected members. What I am not sure is whether or not -it is correct!! The situation - - class A - { - protected:: - A(); - ~A(); - void* data; - }; - - class B : public A - { - public: - B(); - ~B(); - A* next; - }; - -So B is derived from and A and an instance of class B can access the -field data without problems. However, if the class B uses an instance -of class A inside one of its members, for example: - - - B::~B() - { - while (next != this) - { - delete next; - } - } - -The compiler will not permit this access saying that the destructor is -protected. The same thing happens if one tries to access next->data. -Is this correct or is the compiler being too strict? If it's correct -is there any point in having a protected, non-virtual destructor - it -might as well be private. - -This happens with both C++ 2.0 and g++ 1.36.1 . In article <1111@mit-amt.MEDIA.MIT.EDU> peter@media-lab.media.mit.edu (Peter Schroeder) writes: >[...] >This is correct. As a member of B, A* is just some class and can only be >accessed as allowed by the original class definition. > >If we defined a class D which looks exactly like class A and then replaced >the occurence of A* in B by D* it would be clear that we cannot expect to >be able to access D's desctructor. > >I stumbled over this a few times, since 1.2.1 of cfront did not seem to >enforce it, but I can now see that it makes sense to forbid this. > >Hope this helps. This problem was discussed here some 2 months (?) ago. I and someone else argued that the old principle is logical insofar as the unit of encapsulation in C++ is a class (and not an object as in Smalltalk, say). Of course there are arguments in favour of the new principle, too. However, with regard to the much-advertised "stability" of C++ the _change_ was unfortunate. This restriction is explicitly written in section 11.5 of the new C++ Reference Manual (thank you, Bjarne, for sending me a copy). To solve the problem in the original question, it seems necessary to declare B also a friend of A. This means that the definition of A must be changed when such derived classes are added, which may not always be convenient. One possible trick to circumvent this comes to mind, but I cannot deduce from the Ref.Man. whether it is legal in current C++: Define a dummy class AA and declare it a friend class of A. Then, since we now have multiple inheritance, make AA another public base class of B. If classes derived from a friend class of A remain friends of A, this should work, otherwise not. Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland
sakkinen@tukki.jyu.fi (Markku Sakkinen) (11/30/89)
Sorry, I posted the previous article without thinking about this: _If_ the trick suggested at the end (deriving from a dummy friend class) works, then of course B gains access to private members of A as well. This is an unwanted consequence. Perhaps a "half-friend" declaration should be added to C++, allowing access to protected but not to private members ('acquaintance' has been pre-empted for other purposes :-) ). Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland
jaa@hutcs.hut.fi (Jari Alasuvanto) (06/21/90)
We ran into the following problems when switching from 1.2 (Glockenspiel) to 2.0 (Sun). Let's make a simple example: class first { int val2 ; protected: void foo() ; } ; class second : public first { int val ; } ; class third : public first { void bar(second& ref) ; } ; void first::foo() {} void third::bar(second& ref) { ref.foo() ;} produces an error message on sparc, Sun's 2.00 CC "tmp.cxx", line 22: error: third::bar() cannot access first::foo(): protected member 1 error but passes OK with Glockenspiel 1.2 on sun3. The question is: Is this a new (redefined) feature of 2.0 or does one of the compilers have a bug in handling this kind of code ? Thanks in advance, sorry if this has been asked earlier in this group. Jari Alasuvanto -- Jari Alasuvanto Lab. of Information Proc. Science, Helsinki Univ. of Techology, Finland Internet: jaa@hutcs.hut.fi Bitnet: jaa%finhutcs.bitnet tel: +358-0-451 3236 fax: +358-0-465 077