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();
Related
I was programming Vulkan based renderer but unfortunately this error appeared:
'Azazel::Instance::~Instance': cannot access private member declared in class 'Azazel::Instance'
It gives me a headache. I tried to predeclare Azazel_Menager class at start of my namespace,
but it did not work as well so I changed:
friend class Azazel_Menager;
to:
friend class Azazel::Azazel_Menager;
well it did not do the trick as well. So here I'm asking for your help.
maybe you will see something I did not.
Azazel_Menager:
#pragma once
#include "Engine/Core/UsingTypes.h"
namespace Azazel
{
class Instance;
class PhysicalDevice;
class Azazel_Menager
{
public:
static void CreateInstance();
static void RetrieveAndSetPhysicalDevice();
private:
static Ref<Instance> s_Instance;
static Ref<PhysicalDevice> s_PhysicalDevice;
};
}
Instance.h:
#pragma once
#include <vector>
#include <VulkanSDK/include/vulkan/vulkan.hpp>
namespace Azazel
{
class Azazel_Menager;
class Instance
{
friend class Azazel::Azazel_Menager;
private:
Instance();
~Instance();
public:
vk::UniqueInstance m_Instance;
VkDebugUtilsMessengerEXT m_callback;
};
}
Ref = std::shared_ptr
You probably use constructor/destructor outside of Azazel_Menager (as in std::make_shared or in default Deleter).
You have to use them exclusively in Azazel_Menager, as:
void Azazel_Menager::CreateInstance()
{
s_Instance = std::shared_ptr<Azazel::Instance>{new Azazel::Instance{},
[](auto* p){ delete p; }};
}
Demo
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
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.)
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 */ };
}
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).