How to access parent methods from embedded class in PIMPL pattern - c++

I have found a similar question here, but my intent is little different.
class B is the embedding class while class A is the embedded class. I want to let B::A have access to member functions of class B. I have seen compilation errors through g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2. The detailed errors are as follows:
~/Documents/C++ $ g++ embed.cpp
embed.cpp:5:7: error: ‘B’ has not been declared
embed.cpp: In constructor ‘B::B()’:
embed.cpp:10:27: error: invalid use of incomplete type ‘struct B::A’
embed.cpp:14:9: error: forward declaration of ‘struct B::A’
Is there a way that I can make it work?
Thank you
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(new B::A(this)) {}
~B(){}
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent) : parent(_parent) {} // let embedded class A has access to this parent class
~A() { parent = NULL; }
B* parent;
};
int main(void)
{
return 0;
}

This problem is solved easily if you follow the convention of having the header in one file and the implementation in another.
In file b.h:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
class B::A
{
public:
A(B* _parent);
~A();
B* parent;
};
In file b.cpp:
B::B(void)
:impl(new A(this))
{
}
//other methods and such
My compiler was giving me a different error: in the constructor for B, you were default-constructing an object that had no default constructor (because it's an incomplete class). The solution is to implement the B constructor after class A has been fully defined, and the header/implementation separation is a natural way to achieve that.

Just separate the definition from the declaration:
class B
{
public:
B();
~B();
private:
class A; // want to hide the implementation of A
A* impl;
};
// define class B::A
B::B() : impl(new B::A(this)) { }
B::~B() { }
By the time you need to call B::A::A(), it'll already be defined.
You could separate this into three files, B.hpp, BA.hpp and B.cpp, and you would only need to ship B.hpp to the client.

You just can't. If you want to use A, then you have to know all about A. But there maybe another approach:
#include <iostream>
#include <string>
using namespace std;
class B
{
public:
B() : impl(newA()) {}
~B(){}
private:
static Abase *newA();
class Abase{}; // want to hide the implementation of A
Abase* impl;
friend class A;
};
And you define you class A : B::Abase in another file, and implement B::newA() to return a pointer to A.
Code not tested.

Related

How to access private class variable from non-member function [duplicate]

This question already has answers here:
When should you use 'friend' in C++?
(31 answers)
Closed 1 year ago.
From the below code snipped, need to access member function of class A::B. Since class B is private unable to create object for it from non-member function. Kindly help me in getting resolve out of this without moving Class B into public
Code below for reference
A.h
#include <iostream>
class A
{
public:
A();
void Func();
private:
class B;
B *b;
};
A.cpp
#include "A.h"
#include "AB.h"
A::A()
{
b = new B(this);
}
void A::Func()
{
b->Func();
}
AB.h
#include "A.h"
class A::B
{
public:
B(A* a);
void Func();
private:
A* ptr;
};
AB.cpp
#include "AB.h"
A::B::B(A* a):ptr(a)
{
}
void A::B::Func()
{
std::cout<<"Do nothing ";
}
static void call_sample()
{
A::B* tmp;
//access member function of class A::B
}
Error below for reference:
In file included from AB.cpp:2:0:
AB.h: In function ‘void call_sample()’:
AB.h:3:10: error: ‘class A::B’ is private
class A::B
^
AB.cpp:15:4: error: within this context
A::B* tmp;
B is a nested class from A, and it is private, so, as a definition, it is not accessible from the outside. If you need to use B you can decleare B in the public part of A, and then you can use A::B* type.

Access protected data member via friend member function

EDIT:
The original program has multiple files as shown in here
I'm trying to access protected data member in my class from a friend member function of a different class.
I keep getting an access error:
9:32: error: invalid use of incomplete type 'class b' 5:7: error:
forward declaration of 'class b' In member function 'void b::f(a*)':
12:13: error: 'int a::i' is protected 20:47: error: within this
context
This is my code:
// Example program
#include <iostream>
#include <string>
class b;
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
class b{
public:
void f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
};
int main()
{
a a1;
b b1;
b1.f(&a1);
}
The issue is only superficially related to friend. It's rather due to circular dependencies of class definitions and member functions; a needs to know the definition of b because it refers to b::f. But the definition of b::f needs the definition of a, as it refers to a::i. Luckily, definitions of a class and its member functions can be separated from each other.
You can take the following measures to tackle this step by step:
declare class a;
define class b { /* ... */ };, but without defining its member functions (as they need access to a's definition
define class a { /* ... */ };, possibly with inline member function definitions
and finally define b's member functions.
This is how it looks like:
// Step 1:
class a;
// Step 2:
class b{
public:
void f(a* pointer);
};
// Step 3:
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
// Step 4:
void b::f(a* pointer)
{
std::cout<<pointer->a::i<<std::endl;
}
At the point where you try to declare the method of b a friend via friend void b::f(a* pointer);, the class b is incomplete. You cannot refer to members yet. On the other hand, b only needs a forward declaration for a:
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer){std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}
Try this. You are trying to reference b::f before class b is defined.
// Example program
#include <iostream>
#include <string>
class a;
class b{
public:
void f(a* pointer);
};
class a{
public:
friend void b::f(a* pointer);
protected:
int i = 6;
};
void b::f(a* pointer)
{std::cout<<pointer->a::i<<std::endl;}
int main()
{
a a1;
b b1;
b1.f(&a1);
}

Inherit constructors via using but make it out-of-line

Consider the following short but multifile example:
// ************************** unit.h **************************
#pragma once
#include <memory>
struct S;
struct B {
B(int) {};
virtual ~B() {};
};
struct D : B {
D(int);
~D() override;
std::unique_ptr<S> p;
};
// ************************** unit.cpp **************************
#include "unit.h"
struct S {};
D::D(int i) : B(i) {}
D::~D() = default;
// ************************** prog.cc **************************
#include "unit.h"
int main()
{
D d(42);
}
There are two classes with inheritance: base B and derived D. D class contains a unique_ptr member definition with only declared class S. To make this scheme work I need to define both constructor and destructor of class D out-of-line (i.e. implemented in unit.cpp, where the full definition of S is visible).
The question: is it possible to use the using B::B; declaration in the D class inherit the B's constructors to prevent writing manually D::D(int i) : B(i) {}, but make this inheritance out-of-line in order to prevent compilation error?
error: invalid application of 'sizeof' to an incomplete type 'S'
is it possible to use the using B::B; declaration in the D class inherit the B's constructors to prevent writing manually D::D(int i) : B(i) {}
It is possible.
Along with the forward declaration of struct S also declare its deleter:
struct S;
struct SDeleter { void operator()(S*) const; }; // Defined elsewhere.
And then:
struct D : B {
using B::B;
std::unique_ptr<S, SDeleter> p;
};
The definition of void SDeleter::operator()(S*) const must be provided in another translation unit (.cc) that has access to the definition of S.

Complex Circular Dependency among classes

I have 5 classes (A,B,C,D,E), each of which will have their own class and header files.
class A{};
class B
{
B(A&a);
};
class C
{
C(B&b);
};
class D:public A
{};
class E:public D
{
vector<C*> vc;
};
Forward declaration will not work because I also have a lot of sharepointers being used in each of those classes.
You can use forward declarations for shared pointers as well, you just need to forward declare a destructor function object as well.
Header:
struct A;
shared_ptr<A> create_A();
Impl:
struct A { ... };
struct A_destroyer { void operator()(A *p) { delete p; } };
shared_ptr<A> create_A() { return shared_ptr<A>(new A(), A_destroyer()); }
Each class can declare a destructor and define that destructor in a source including the header for the appropriate type destructed by unique/shared pointer. Than a simple forward of that type in the header will do it.
#include <memory>
// header B
struct A;
struct B {
~B();
std::shared_ptr<A> a;
};
// header A
struct A {};
// source B
#include "a"
#include "b"
B::~B() {}

How do I access a private constructor in a separate class?

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.
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();
};
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() {}
};
Live Example.
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;
}
You can make B a friend of A:
class A
{
private:
A();
friend class B;
};