this is a follow-up question to friend function within a namespace
If I want testFunc to be in namespace TestNamespace, but I don't want TestClass also in TestNamespace, how can I declare them?
1.This doesn't work ("expected unqualified-id before namespace" on line 2)
class TestClass {
namespace TestNamespace {
friend void testFunc(TestClass &myObj);
};
}
namespace TestNamespace {
void testFunc(TestClass &myObj);
}
2.But it complains that "TestNamespace::testFunc(...) should have been declared inside 'TestNamespace'" when I do this-
class TestClass {
friend void TestNamespace::testFunc(TestClass &myObj);
}
namespace TestNamespace {
void testFunc(TestClass &myObj);
}
3.The above code is okay if I don't have the "TestNamespace::" in the friend function declaration on line 2, but I'm not sure if it then knows that TestNamespace::testFunc is a friend.
I don't know what's happening in any of these cases. Any insight would be much appreciated too. Thanks!
Try using forward declarations:
class TestClass;
namespace TestNamespace {
void testFunc(TestClass &myObj);
}
class TestClass {
friend void TestNamespace::testFunc(TestClass &myObj);
};
I don't know what "leda" was in your original example, but hopefully you can substitute whatever names you need given the above.
You can make it simple:
class TestClass; // forward declaration
namespace TestNamespace { // namespace body
void testFunc(TestClass &myObj); // passing by reference, ok!
}
class TestClass {
friend void TestNamespace::testFunc(TestClass &myObj); // scoping with namespace
};
Remember, namespace body can be only in global scope (not inside class or function).
Related
Is it possible to use class name which declare in namespace without namespace?
I tried like this:
//MyClass.h
namespace MyNamespace {
class MyClass;
}
class MyNamespace::MyClass {
public:
/* ... */
}
//MyOtherClass.cpp
#include "MyClass.h"
using namespace MyNamespace;
void MyOtherClass::MyFunction() {
MyClass *myClass = new MyClass;
}
But it doesn't work.
Complier says "MyClass is ambiguous."
I guess this code would work :
//MyOtherClass.cpp
#include "MyClass.h"
using namespace MyNamespace;
void MyOtherClass::MyFunction() {
MyNamespace::MyClass *myClass = new MyClass;
}
But it is uncomfortable for me.
I wanna use 'MyClass' without "MyNamespace::".
Is it possible?
Thanks for your help.
I got answer : It is not possible.
C++ classes have own default namespace. If I declare MyNamespace, then there is two namespaces associated with MyClass. If I use MyClass without choosing what namespace I want to use, Compiler feel ambiguous what namespace I really wanted to use. So it would tell me "MyClassis ambiguous."
if the below code is all in the same .h file (you did not really clarify)
//MyClass.h
namespace MyNamespace {
class MyClass;
}
class MyNamespace::MyClass {
public:
/* ... */
}
Then what you are doing a forward declaration of MyNamespace::MyClass in the first part.
You should have something like this in MyClass.h
namespace MyNamespace {
class MyClass
{
public:
// constructor, methods,...
}; // end of class declaration
} // end of namespace
and the associated definition in MyClass.cpp
namespace N
{
template<typename tname> class C
{
public:
friend void f(int, C<tname>);
};
}
template<typename tname>
void N::f(int, N::C<tname>)
{
}
I am creating a friend function f like above but the compiler informed me this error :
'f': is not a member of N.
Meanwhile, without the namespace, my code will run correcly.
My code will be correct too when I use normal class instead of generic class (no remove namespace).
And it will also have no error with fully declaration. Like following code:
namespace N
{
template<typename tname> class C
{
public:
friend void f(int, C<tname>)
{
//mycode
}
};
}
Could someone help me fix this error in my first code? Thank you very much.
The friend declaration does not mean that the function is now a member of that class. It only means that f has access to the private members of C.
So if f is in the global namespace it cannot be referenced as being inside namespace N with N::f, it is still only a ::f, even after the friend declaration.
In the second example you're declaring f as a member function and declaring it a friend which I'm not sure serves a purpose.
The following compiles:
namespace N
{
template<typename tname>
class C;
template<typename tname>
void f(int, C<tname>);
template<typename tname> class C
{
public:
friend void f(int, C<tname>);
};
}
template<typename tname>
void N::f(int, N::C<tname>)
{
}
int main()
{
}
I'm having a compilation error using Apple's Clang 7.0 with the following friendship code, using C++11 standard. I wonder what's really wrong with it since it seems to be valid for me. I'm describing the setting and the error I'm having:
MyInterface
namespace namespace1
{
class MyInterface
{
friend class MyClass;
public:
virtual void some_method(void) = 0;
...
private:
type some_attribute;
...
}
}
MyClass::MyMethod Implementation
namespace namespace2
{
void MyClass::MyMethod(MyInterface* MyConcrete)
{
...
// MyConcrete implements MyInterface
if(MyConcrete->some_attribute == some_value) // Error*
{
...
}
...
}
}
Error
error: 'some_attribute' is a private member of 'namespace1::MyInterface'
I really expected that MyClass would have access to some_attribute in MyConcrete (which implemented MyInterface) regardless of the class access modifier. Any clues why this error is happening? Any suggestions?
Thank you!
MyClass is in namespace2. So you need to use:
friend class namespace2::MyClass;
You may also need to use forward decleration of MyClass before you define MyInterface.
Here's an example that compiles:
// forward decleration
namespace namespace2
{
class MyClass;
}
namespace namespace1
{
class MyInterface
{
friend class namespace2::MyClass; // added missing namespace
public:
virtual void some_method(void) = 0;
private:
int some_attribute;
};
}
namespace namespace2
{
class MyClass
{
void MyMethod(namespace1::MyInterface* MyConcrete)
{
if(MyConcrete->some_attribute == 1)
{
}
}
};
}
int main()
{
}
You can run it here.
friend class MyClass; in the context of ::namespace1::MyInterface refers to the class ::namespace1::MyClass, which is a different class from ::namespace2::MyClass. (That's the whole point of namespaces, right?)
Change the friend declaration to read like this:
friend class ::namespace2::MyClass;
Note that this requires that the type ::namespace2::MyClass has already been declared, so you either need to forward-declare it (namespace namespace2 { class MyClass; }) or you need to make sure that the definition is included prior to the definition of ::namespace1::MyInterface.
(See this demo.)
I need to create a dynamic library:
mylib.h
class FriendClass;
namespace my_namespace
{
class MyLib
{
friend class FriendClass;
public:
MyLib();
/* public functions */
private:
void function_for_friend_class();
};
} // namespace my_namespace
And use it here
friend_function.h
class FriendClass
{
public:
void some_function()
{
MyLib* my_lib = get_my_lib_somehow();
my_lib->function_for_friend_class();
}
};
With gcc3.4 it compiles, but gcc4.9 complains that function_for_friend_class is private. What am I doing wrong?
Use friend class ::FriendClass;
By doing this, you tell the compiler to look in the global namespace of the definition of class FriendClass, not in the current namespace.
Also use:
my_namespace::MyLib* my_lib = get_my_lib_somehow();
If the class G is in the namespace GSpace and it needs to be friends with the class M in the global namespace what do you have to do? I thought this would work:
/////////////////////M.h//////////////////////
#include "GFile.h"
class M
{
public:
friend class GSpace::G; // doesn't work, throws error
}
After researching on StackOverflow a bit, I found this answer https://stackoverflow.com/a/3843743/1797424
/////////////////////M.h//////////////////////
namespace GSpace
{
class G;
}
class M
{
public:
friend class GSpace::G; // works, no error
private:
GSpace::G gClassMember; // errors: "M uses undefined class GSpace::G"
};
// Note that G.h includes M.h so I do not include it here,
// instead I have it included in M.cpp
That does work for getting the class friended. However, it creates an issue when I actually declare a class member using that type, because the class is not defined. GFile.h
Am I misunderstanding how #include and forward declaration behaves, or is it some kind of implementation issue on the side of the compiler (not likely, I'm assuming)?
Because your member is not a pointer or reference, the compiler needs to know the size of G. You can't use a forward declaration.
As noted in the comment, you need to qualify G with the namespace.
Here is code which compiles for me:
namespace GSpace
{
class G
{
};
}
class M
{
public:
friend class GSpace::G;
private:
GSpace::G gClassMember;
};
int main() {return 0;}
Try the following
namespace GSpace
{
class G;
}
class M
{
public:
friend class GSpace::G;
}
namespace GSpace
{
class G { /* definition of the class */ };
}