473,395 Members | 1,677 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Problems with protected variables despite friends

Hello, consider this program:
class Outer
{
public:
class Base
{
friend class Outer;
public:
Base(int n) : n_(n) {}
protected:
int n_;
};

class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};

class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};
};

int main()
{
Outer::Child1 c1(4711);
Outer::Child2 c2(c1);
}

It compiles with MSVC++ 8.0 SP1 and gcc 4.2.0. It does not compile
with gcc 3.4.4:
$ g++ -Wall -Wextra -std=c++98 -pedantic -g foo.cpp -o runme.exe
foo.cpp: In constructor `Outer::Child2::Child2(const Outer::Child1&)':
foo.cpp:10: error: `int Outer::Base::n_' is protected
foo.cpp:27: error: within this context

Also, worth mentioning is that gcc 4.2.0 doesn't need quite as many
friend declarations as MSVC++ 8.0 SP1 does...is this code valid
according to the standard and is it being rejected by the older gcc
because of a bug or a failure to follow the standard as closely as gcc
4.2.0?

It's not an academic question for me, I encountered this problem in a
real program and this my reduced test case.

- Eric

May 30 '07 #1
4 2973
Eric Lilja wrote:
Hello, consider this program:
class Outer
{
public:
class Base
{
friend class Outer;
public:
Base(int n) : n_(n) {}
protected:
int n_;
};

class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};

class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};
};

int main()
{
Outer::Child1 c1(4711);
Outer::Child2 c2(c1);
}

It compiles with MSVC++ 8.0 SP1 and gcc 4.2.0. It does not compile
with gcc 3.4.4:
$ g++ -Wall -Wextra -std=c++98 -pedantic -g foo.cpp -o runme.exe
foo.cpp: In constructor `Outer::Child2::Child2(const Outer::Child1&)':
foo.cpp:10: error: `int Outer::Base::n_' is protected
foo.cpp:27: error: within this context

Also, worth mentioning is that gcc 4.2.0 doesn't need quite as many
friend declarations as MSVC++ 8.0 SP1 does...is this code valid
according to the standard and is it being rejected by the older gcc
because of a bug or a failure to follow the standard as closely as gcc
4.2.0?
I think so, as far as I know your program is correct for the standard.
To let the code compile with g++ 3.4, try considering a forward declaration:

class Child2;

class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};

class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};

it should work.

Regards,

Zeppe
May 30 '07 #2
On 30 Maj, 14:52, Zeppe <zep_p@.remove.all.this.long.comment.yahoo.it>
wrote:
Eric Lilja wrote:
Hello, consider this program:
class Outer
{
public:
class Base
{
friend class Outer;
public:
Base(int n) : n_(n) {}
protected:
int n_;
};
class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};
class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}
Child2(const Child1& rhs) : Base(rhs.n_) {}
};
};
int main()
{
Outer::Child1 c1(4711);
Outer::Child2 c2(c1);
}
It compiles with MSVC++ 8.0 SP1 and gcc 4.2.0. It does not compile
with gcc 3.4.4:
$ g++ -Wall -Wextra -std=c++98 -pedantic -g foo.cpp -o runme.exe
foo.cpp: In constructor `Outer::Child2::Child2(const Outer::Child1&)':
foo.cpp:10: error: `int Outer::Base::n_' is protected
foo.cpp:27: error: within this context
Also, worth mentioning is that gcc 4.2.0 doesn't need quite as many
friend declarations as MSVC++ 8.0 SP1 does...is this code valid
according to the standard and is it being rejected by the older gcc
because of a bug or a failure to follow the standard as closely as gcc
4.2.0?

I think so, as far as I know your program is correct for the standard.
To let the code compile with g++ 3.4, try considering a forward declaration:

class Child2;

class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};

class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};

it should work.

Regards,

Zeppe
That doesn't help at all and I think the friend declaration is a
forward declaration in itself.

May 30 '07 #3
Eric Lilja wrote:
On 30 Maj, 14:52, Zeppe <zep_p@.remove.all.this.long.comment.yahoo.it>
wrote:
>I think so, as far as I know your program is correct for the standard.
To let the code compile with g++ 3.4, try considering a forward declaration:
That doesn't help at all and I think the friend declaration is a
forward declaration in itself.
yes, it is, according to the standard. But in my system (linux + gcc
version 3.4.6), adding a further forward declaration it's enough to let
the program compile correctly (your original program didn't worked on my
gcc 2.4 as well). If the follow (copied and pasted from the source that
compiles on my gcc 3.4) still doesn't compile on your gcc 3.4, I don't
know what to suggest you...

class Outer
{
public:
class Base
{
friend class Outer;
public:
Base(int n) : n_(n) {}
protected:
int n_;
};

class Child2;

class Child1 : public Base
{
friend class Outer;
friend class Child2;
public:
Child1(int n) : Base(n) {}
};

class Child2 : public Base
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};
};

int main()
{
Outer::Child1 c1(4711);
Outer::Child2 c2(c1);
}

regards,

Zeppe
May 30 '07 #4
On May 30, 1:35 pm, Eric Lilja <mindcoo...@gmail.comwrote:
Hello, consider this program:
class Outer
{
public:
class Base
{
friend class Outer;
public:
Base(int n) : n_(n) {}
protected:
int n_;
};
class Child1 : public Base
{
friend class Outer;
friend class Child2;
The standard is far from clear about this, but the most
reasonable interpretation of the current version is that
this declares (and refers to) a class at namespace scope.
At least, that would seem to be the intent: from a note
(non-normative) in §3.3.1/8 (of the latest draft): "friend
declarations refer to functions or classes that are members
of the nearest enclosing namespace,[...]". The note is,
however, contradicted in §11.4/11, where it says:For a
friend class declaration, if there is no prior declaration,
the class that is specified belongs to the innermost
enclosing non-class scope,[...]", but the first sentence of
the paragraph starts "If a friend declaration appears in a
local class[...]" and this "if" seems to be meant to apply
to the entire paragraph, and not just the first sentence.

Note that the text concerning friendship is still somewhat
in a state of flux. The next version of the standard will
differ considerably from the current one, and may differ
from the text in the latest draft as well. Also: since the
text is excedingly unclear, and in a state of flux,
compilers will vary greatly with regards to what they
actually do.
parent[(*this).header] = y; // Update root.
else if (x == left[parent[x]])
left[parent[x]] = y;
else
right[parent[x]] = y;
public:
Child1(int n) : Base(n) {}
};
class Child2 : public Base
Note that according to the above interpretation, this is
*not* the class that Child1 declared as a friend.
{
friend class Outer;
public:
Child2(int n) : Base(n) {}

Child2(const Child1& rhs) : Base(rhs.n_) {}
};
};
int main()
{
Outer::Child1 c1(4711);
Outer::Child2 c2(c1);
}
It compiles with MSVC++ 8.0 SP1 and gcc 4.2.0. It does not compile
with gcc 3.4.4:
$ g++ -Wall -Wextra -std=c++98 -pedantic -g foo.cpp -o runme.exe
foo.cpp: In constructor `Outer::Child2::Child2(const Outer::Child1&)':
foo.cpp:10: error: `int Outer::Base::n_' is protected
foo.cpp:27: error: within this context

Also, worth mentioning is that gcc 4.2.0 doesn't need quite as many
friend declarations as MSVC++ 8.0 SP1 does...
It's possible the g++ is already implementing parts of the
newer standard, which will (I think) make member classes
implicitly friends (or more precisely, a member class is a
member of the enclosing class, and thus has access to
private and protected members of that class).

Note that I've not followed this evolution very closely,
and I could be wrong with regards to many of the details.
The important point to keep in mind, I think, is that it
isn't clear, it is evolving, and that compilers will vary
enormously. About the one point that does seem clear (at
least to me) is that the compiler does do name lookup as if
the friend specifier was absent, and IF it finds the name,
that is what is being declared friend. Thus, in the above
case, you might start with:

class Outer
{
public:
class Base ;
class Child1 ;
class Child2 ;

// ...
} ;

This ensures that any later references to Outer::Base,
Outer::Child1 or Outer::Child2 will find the correct class
(and be legal---if qualified name look-up fails, I think it
is an error).
is this code valid according to the standard and is it
being rejected by the older gcc because of a bug or a
failure to follow the standard as closely as gcc 4.2.0?
I think part of the motivation for the rewrite in the
standard is that interpreted literally, the current standard
makes it impossible to declare a nested class friend. This
was never the intent, and as far as I know, was never
actually implemented by any compiler. What compilers did
implement, however, varied, and will continue to vary, at
least until the next version of the standard is released and
compilers implement it.

If you want to really know what is being planned, and how
this is evolving, I'd suggest asking the question in
comp.std.c++. Be aware, however, that this won't
necessarily help you now, with the compilers you have today.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 31 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Kevin Saff | last post by:
Apparently I'm missing something. Stroustrup (15.3) says of protected access: If is protected, its name can be used only by member functions and friends of the class in which it is declared...
3
by: fabio de francesco | last post by:
Hello, I have written this code that compiles without errors ( "..." stays for code that I don't post for the sake of brevity): // Person.h .... class Person { public:
5
by: Daniel Aarno | last post by:
Can anyone provide a good explanation to why the following does not work? After all since A is a public base of B objects of type B ISA object of type A. class A { protected: void foo() {} };...
4
by: baumann | last post by:
hi all, according the private / protected access control, - private; that is, its name can be used only by members and friends of the class in which it is declared. - protected; that is,...
0
by: netgeni59 | last post by:
Hello fellow C# friends, I am trying to write a C# TCP client that was formerly written in Java. The server must still remain in Java. I cannot get text data from the C# client to be received...
5
by: Mark Hanson | last post by:
I would like to access code behind .aspx.vb protected variables from the aspx web page like this <%# _ProtectedVariable %>. The only way I can get the value is if I do Me.DataBind on each...
11
by: Kevin Prichard | last post by:
Hi all, I've recently been following the object-oriented techiques discussed here and have been testing them for use in a web application. There is problem that I'd like to discuss with you...
11
by: radders | last post by:
I've just started working through Sams publishing's "Teach yourself Visual C++ 4 in 21 days", using VC++ version 4.0 on a windows xp machine. My problem occurs when I attempt to add member variables...
15
by: =?Utf-8?B?R2Vvcmdl?= | last post by:
Hello everyone, I met with a strange issue that derived class function can not access base class's protected member. Do you know why? Here is the error message and code. error C2248:...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.