LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-12-2007, 02:23 AM   #1
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Rep: Reputation: 15
Question friend class doesn't work when I put in namespace?


Here is a simple c++ program that demonstrates friend classes:

Code:
class A {
friend class B;

private:
	int var;
};

class B {
public:
	int GetVar() { return myA.var; }

private:
	A myA;
};

int main() {}
The above code compiles just fine. However, when I put class A into a namespace, like so:

Code:
namespace wk {

class A {
friend class B;

private:
	int var;
};

} // namespace wk

class B {
public:
	int GetVar() { return myA.var; }

private:
	wk::A myA;
};

int main() {}
The above code does not compile. I get the following error message:
Code:
wk@ALPHA:~/cprog$ g++ -o tmp tmp.cpp
tmp.cpp: In member function 'int B::GetVar()':
tmp.cpp:7: error: 'int wk::A::var' is private
tmp.cpp:14: error: within this context
I can put class A in a namespace, but only if I make var public, like so:

Code:
namespace wk {

class A {
public:
	int var;
};

} // namespace wk

class B {
public:
	int GetVar() { return myA.var; }

private:
	wk::A myA;
};

int main() {}
The above code compiles just fine, without error.

Does anyone know why this is? It looks like using namespaces nullifies friend classes. I couldn't find any mention of this in any of the c++ references that I found on the internet. Is there a way to keep A.var private, while keeping it in a namespace?

Last edited by Winter Knight; 12-12-2007 at 02:24 AM.
 
Old 12-12-2007, 03:00 AM   #2
Looking_Lost
Senior Member
 
Registered: Apr 2003
Location: Eire
Distribution: Slackware 12.0, OpenSuse 10.3
Posts: 1,120

Rep: Reputation: 45
Only learning C++ myself, but I found if you stick a forward declaration of class B at the top of your file it will compile, scope issue maybe ?

Code:
class B;

namespace wk {

class A {
friend class B;

private:
	int var;
};

} // namespace wk

class B {
public:
	int GetVar() { return myA.var; }

private:
	wk::A myA;
};

int main() {}
 
Old 12-12-2007, 07:16 AM   #3
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
The code you displayed does not compile for me. I get the same error. What compiler are you using? I'm using Debian stock kernel, g++ 4.2.2-4.
 
Old 12-12-2007, 07:25 AM   #4
Looking_Lost
Senior Member
 
Registered: Apr 2003
Location: Eire
Distribution: Slackware 12.0, OpenSuse 10.3
Posts: 1,120

Rep: Reputation: 45
On a windows machine at the moment using CYGWIN environment, gnu g++ 3.4.4
 
Old 12-12-2007, 07:41 AM   #5
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
I just downloaded, installed, and tried g++-3.4 on your version of the program, and I get the same results as you. I wonder which one is correct. I still don't understand why my original doesn't compile. Their shouldn't be a scope issue, because the code inside a block, such as the "wk" namespace, should be able to see outside of it's block. It's just that nobody should be able to see inside without fully qualifying (which I do).

This might be a compiler bug, but I'm not sure. I've thought that before, and then someone comes along and shows me my error.
 
Old 12-12-2007, 08:19 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,781

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
The following works for me on g++ version 4.2.3
Code:
class B;

namespace wk {

class A {
friend class ::B;

private:
	int var;
};

} // namespace wk

class B {
public:
	int GetVar() { return myA.var; }

private:
	wk::A myA;
};

int main() {}
 
Old 12-12-2007, 08:25 AM   #7
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
Thanks. That works for me too. It still seems odd, though.
 
Old 12-12-2007, 10:39 AM   #8
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
ntubski reply is correct and it is due to scope(namespace issue), by leaving out the scope operator you are saying the class is in the same namespace as the other class. ie
Code:
namespace BAR{ class Bar{};}
class Bar{};
namespace FOO{ 
class Bar{};
class Foo
{
friend class Bar;//says Bar is really FOO::Bar
firend class ::Bar;//says Bar is a member of the global namespace
firend class BAR::Bar;//says Bar is a member of the BAR namespace
}
; 
}
plus you have to forward declare the class.

Last edited by dmail; 12-12-2007 at 10:43 AM. Reason: added class FOO::Bar to show the usefulness of it
 
Old 12-12-2007, 08:20 PM   #9
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
OK. Thanks. I get the part about scope. But why do you have to forward declare only if you use a namespace, but not if the two classes are in the same namespace?

For example, this works:
Code:
class A {
friend class B;

private:
	int var;
};

class B {
public:
	int GetVar() { return myA.var; }

private:
	A myA;
};

int main() {}
But this doesn't:
Code:
namespace wk {

class A {
friend class ::B;

private:
	int var;
};

} // namespace wk

class B {
public:
	int GetVar() { return myA.var; }

private:
	wk::A myA;
};

int main() {}
In the second example, of course, it works if I forward declare class B.
 
Old 12-12-2007, 11:35 PM   #10
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Strictly speaking, this is the correct behavior. Here's why:

http://womble.decadentplace.org.uk/c...ax-errors.html

Here's a more detailed explanation:

http://www.open-std.org/jtc1/sc22/wg...000/n1229.html

And here's a very short explanation:
Quote:
You have to declare friendship to the function in the namespace, not
to a non-existent global one.
...
Just to be accurate, you'll get a bunch of errors since
1) mynamespace is undeclared at this point
2) the Bar declaration has no return value

http://www.thescripts.com/forum/thread62918.html
This is a good example (one of many) why I think C++ is a *terrible* language for beginners - there are just too many subtle "surprises" for anybody but advanced C++ programmers to have to deal with.

IMHO ... PSM
 
Old 12-13-2007, 12:57 PM   #11
Winter Knight
Member
 
Registered: Nov 2005
Distribution: Debian Stable/Testing
Posts: 54

Original Poster
Rep: Reputation: 15
Thanks for the links, paulsm4. It helped me understand the situation a lot. Here is an especially interesting quote from the second link:

"The wording in the standard regarding the handling of names declared in unqualified friend declarations is unclear and, in certain cases, clearly incorrect."
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
operator= doesn't work with a template class The_Nerd Programming 1 05-22-2006 02:54 PM
C++ Vector Class without Namespace sadarax Programming 6 02-02-2006 05:20 PM
c++ class template doesn't work!! tagigogo Programming 2 11-02-2005 04:45 PM
How to make my class work with ostream_iterator danxl Programming 1 04-07-2004 01:41 PM
where to put bean class files ? ihasircioglu Programming 0 12-11-2003 04:20 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:31 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration