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-8232peter@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)
Finlandjaa@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