Reputation: 8208
I'm writing a library in C++. I have two classes in my library, A
and B
. I want to hide the A()
constructor from any code that references my library. I also want class B
to be able to call the A()
constructor.
I come from a C# background and remember little of my C++. In C#, I would simply declare the A()
constructor as internal
. I've read that the closest way to do this in C++ is a combination of friend
declarations and forward-declarations. How do I do this? Here are my three files below:
A.h:
#pragma once
class A
{
private:
A();
};
B.h
#pragma once
class A;
class B
{
public:
A createA();
};
B.cpp:
#include "A.h"
#include "B.h"
A B::createA()
{
A result; //cannot access private member declare in class 'A'
return result;
}
I've tried adding this to A.h:
public: friend A createA();
I've instead tried adding this to A.h with a corresponding forward declaration:
public: friend A B::createA();
I've instead tried adding and extern class B;
to A.h and making B a class like this:
public: friend class B;
I'm at a loss.
I think this might be easier if I have the B::createA()
function return a pointer to an A
object rather than an A
object directly, but that won't do in my case. I am emulating a closed API and the API call returns an A
object rather than a pointer.
Upvotes: 11
Views: 21052
Reputation: 15870
Unless absolutely necessary, you should have A
construct itself (or have a factory that creates A
). If you really want B
to do it:
class B; // foward declared
class A
{
private:
A() {}
friend class B;
};
class B
{
public:
A CreateA()
{
A a;
return a;
}
};
int main()
{
B b;
A a = b.CreateA();
return 0;
}
Note: You must forward declare B
before declaring it a friend
in A
.
If you want just the function as a friend:
class A;
class B
{
public:
A CreateA();
};
class A
{
private:
A() {}
friend class A B::CreateA();
};
A B::CreateA()
{
A a;
return a;
}
int main()
{
B b;
A a = b.CreateA();
return 0;
}
Upvotes: 1
Reputation: 56883
You probably just need to drop the "extern" from your third attempt to turn it into a proper forward-declaration. Try:
A.h:
#pragma once
class B;
class A
{
friend class B;
private:
A();
};
Upvotes: 9
Reputation: 14510
You don't need the external
keyword. Make it simple:
// In A.h
class B; // Forward declaration
class A
{
friend class B; // Make all the class B friend
A();
};
// In B.h
class B
{
public:
A createA() {}
};
Upvotes: 1
Reputation: 25386
You can make B a friend of A:
class A
{
private:
A();
friend class B;
};
Upvotes: 0