Nameless Union+Struct grants Friends access to Private BaseClass Members?

I'm compiling the following code segment under Visual C++ 2008 Express Edition, and I'm at a loss as to why MEOW and BARK can be accessed, that is, don't cause a compilation error. Is this a compiler specific issue, or am I missing something, and is this supposed to work? Thanks in advance...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class CBase
{
	private:

		int                        iMoo;

		union
		{
			long long          llSqueak;

			struct
			{
				void            *pvMeow;
				long              lBark;
			};
		};

		struct
		{
			char               *pcChirp;
		};
};

class CDerived : private CBase
{
	friend class CFriend;
};

class CFriend
{
	public:

		void fnFriend( CDerived &rD )
		{
			rD.iMoo;		// cannot access private member declared in class 'CBase'
			rD.pvMeow;      // WHY THE FRELL DOES THIS COMPILE?
			rD.lBark;       // WHY THE FRELL DOES THIS COMPILE?
			rD.pcChirp;     // cannot access private member declared in class 'CBase'
			rD.llSqueak;    // cannot access private member declared in class 'CBase'
		}
};
Last edited on
it compiles because that's how anonymous unions work. if you don't want that code to compile then give your union and struct a name.

here, read about anonymous unions
http://cplusplus.com/doc/tutorial/other_data_types/

hope that helps
I gues I'm missing something in 'that's how anonymous unions work'...
Keep in mind my issue is with getting access to PRIVATE members right, not about qualification. I've extended the previous example with another nameless union which behaves as I would expect it to...
Why can I access the private members MEOW and BARK at all?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class CBase
{
	private:

		int                        iMoo;

		union
		{
			long long          llSqueak;

			struct
			{
				void            *pvMeow;
				long              lBark;
			};
		};

		struct
		{
			char               *pcChirp;
		};

		union
		{
			short                sQuack;
			float                fBleat;
		};
};

class CFriend
{
	public:

		void fnFriend( CDerived &rD )
		{
			rD.iMoo;		// cannot access private member declared in class 'CBase'
			rD.pvMeow;      // WHY THE FRELL DOES THIS COMPILE?
			rD.lBark;       // WHY THE FRELL DOES THIS COMPILE?
			rD.sQuack;      // cannot access private member declared in class 'CBase'
			rD.fBleat;      // cannot access private member declared in class 'CBase'
			rD.pcChirp;     // cannot access private member declared in class 'CBase'
			rD.llSqueak;    // cannot access private member declared in class 'CBase'
		}
};
ok here's your answer, CBase does not consider CFriend as a friend.

Another property of friendships is that they are not transitive: The friend of a friend is not considered to be a friend unless explicitly specified.

http://cplusplus.com/doc/tutorial/inheritance/

hope that helps..

Last edited on
I am aware of this, please take a moment to just take a look at what I'm actually asking here in both the topic title and comments. :)

Since the relationship is NOT TRANSITIVE CFriend should not be able to gain access to ANY PRIVATE member of CBase since CFriend is only a friend of CDerived which in turn inherits PRIVATELY from CBase. Thus as far a I understand it, fnFriend() should NOT be able to access MEOW or BARK. But Visual C++ 2008 Express has no issue with it for some reason.
It doesn't allow access to any of the members EXCEPT MEOW and BARK, which leaves me to believe either I'm missing something, or the compiler isn't handling nameless UNION+STRUCT right... It seems to work fine with ONLY a nameless struct (CHIRP) or union (QUACK, BLEAT), but not both. With both it seems to revert back to PUBLIC access, which seems odd to me.
1
2
3
4
5
6
7
8
class CDerived : public CBase {
    friend class CFriend;
    public:
    void test() {
        iMoo = 54; //turns out that CDerived is also not permitted to
                   //access iMoo
    }
};


BTW i'm using MingW compiler and it still works, so this is not a visual studio problem.
Right, because MOO is PRIVATE to CBase right, it would have had access had it been declared PUBLIC or PROTECTED.

http://msdn.microsoft.com/en-us/library/7f45fat0.aspx

But I'm at a loss as to why MEOW and BARK *are* accessible, seriously; why? :)
hmmm. i think because of the property of an anonymous union to allow access to it's nested struct or other union, since there is no name to identify it. if that's the case, accessing lbark means accessing the member of the nested union or struct of the outer union.. not the member of the class CBase..

well that's only my analysis, i have no book to prove it.. but i think your code above is already a proof.
Last edited on
No no no... this looks an awful lot like a compiler bug. Let me try it with a different compiler.

EDIT: gcc 4.3.2 compiles it fine, but comeau does not:

Your Comeau C/C++ test results are as follows:

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 11: error: declaration does not declare anything
struct
^

"ComeauTest.c", line 12: error: types cannot be declared in anonymous unions
{
^

"ComeauTest.c", line 18: error: declaration does not declare anything
struct
^

"ComeauTest.c", line 36: error: class "CDerived" has no member "pvMeow"
rD.pvMeow; // WHY THE FRELL DOES THIS COMPILE?
^

"ComeauTest.c", line 37: error: class "CDerived" has no member "lBark"
rD.lBark; // WHY THE FRELL DOES THIS COMPILE?
^

5 errors detected in the compilation of "ComeauTest.c".

(Note: you can try out the comeau compiler online at:
http://www.comeaucomputing.com/pcgi-bin/compiler.cgi)
Last edited on
can anyone try this using Borland? also please try to replace the inner struct to be union.
Last edited on
Topic archived. No new replies allowed.