Reputation: 5
I'm trying to force function caller from a specific class. For example this code bellow demonstrate my problem. I want to make 'use' function would be called only from class A. I'm using a global namespace all over the project.
a.h
#include "b.h"
namespace GLOBAL{
class A{
public:
void doSomething(B);
}
}
a.cpp
#include "a.h"
using namespace GLOBAL;
void A::doSomething(B b){
b.use();
}
b.h
namespace GLOBAL{
class B{
public:
friend void GLOBAL::A::doSomething(B);
private:
void use();
}
Compiler says:
‘GLOBAL::A’ has not been declared
‘void GLOBAL::B::use()’ is private
Can anyone help here ?
Thanks a lot,
Mike.
Upvotes: 0
Views: 578
Reputation: 62333
The following compiles fine from a cpp file:
namespace GLOBAL
{
class B;
class A
{
public:
void doSomething(B& b);
};
};
namespace GLOBAL
{
class B
{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use()
{
}
};
};
void GLOBAL::A::doSomething(B& b)
{
b.use();
}
As best I can tell your problem arises from the fact that you include "b.h" from "a.h" that defines the B class before the A class is defined yet the B class makes a reference to the A class. So you have problems. However you can't forward declare an object of type B because you are copying via the stack. Hence why I use a reference to class B (as this doesn't require the B object to be known in advance).
Basically you have some fundamental problems with your structure that needs working out. You need to do some reading up on forward declarations and circular dependencies
Edit: Specifying purely that class A is a friend of B (rather than a specific function in A that references B) is actually a possibility as the friend definition provides a kind of forward declaration. As such the following code compiles:
namespace GLOBAL
{
class B
{
public:
friend class A;
private:
void use()
{
}
};
};
namespace GLOBAL
{
class A
{
public:
void doSomething(B b);
};
};
void GLOBAL::A::doSomething(B b)
{
b.use();
}
As such in your code, originally posted, chaging the friend statement to, simply
friend class A;
should allow your code to compile.
Upvotes: 1
Reputation: 264729
This is because in the friend delcaration you are refering to a member of a class.
For this to work the compiler must already have seen the full definition of A.
// #include "b.h" // remove this line it is not needed.
namespace GLOBAL{
class B; // Forward declare the class here.
class A{
public:
void doSomething(B&); // Note: This should probably be a reference.
// Change to doSomething(B&);
}
}
// Add this line it is needed for the friend declaration.
// To have a member as a friend we need the definition of 'A'
#include "a.h"
namespace GLOBAL{
class B{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use();
}
#include "a.h"
// Add this line to include the B definition so you know how to call use()
#include "b.h"
using namespace GLOBAL;
void A::doSomething(B& b){ // b should be a reference otherwise you are copying it.
b.use();
}
Upvotes: 2
Reputation: 76523
Move #include "b.h"
from a.h
to a.cpp
after the first #include
directive. The compiler doesn't need to see the friend declaration until it's compiling the function that the declaration applies to.
Upvotes: 0