Reputation: 336
Let's say I have a class B
and a class A : public B
which inherits from B
. I want to expose the methods of A
, which call some methods in B
.
Now I want to expose these methods in the pimpl idiom - I'm really not sure how to do this:
Do both A
and B
get separate implementation classes B::impl
and A::impl : public B::impl
such that implementations inherit from each-other? The regular classes then don't inherit: class A
and class B
?
I realized this is not possible, since the implementations are private
.
The implementations don't subclass B::impl
and A::impl
but the exposed classes do class B
and class A : public B
. But then how are the methods in A::impl
able to call the methods of the parent in B::impl
?
Via a pointer in the arguments - see example below.
Thanks
Edit: Here is an example code snippet - is this correct?
test.hpp
#include <iostream>
class B {
private:
class impl;
std::unique_ptr<impl> pimpl;
public:
B();
~B();
B(B&&) = default;
B(const B&) = delete;
B& operator=(B&&);
B& operator=(const B&) = delete;
void my_func() const;
};
class A : public B {
private:
class impl;
std::unique_ptr<impl> pimpl;
public:
A();
~A();
A(A&&) = default;
A(const A&) = delete;
A& operator=(A&&);
A& operator=(const A&) = delete;
void access_my_func();
};
test.cpp
#include "test.hpp"
// Implementation of B
class B::impl
{
public:
impl() {};
void impl_my_func() {
std::cout << "impl_my_func" << std::endl;
return;
};
};
// Constructor/Destructor of B
B::B() : pimpl{std::make_unique<impl>()} {};
B::~B() = default;
B& B::operator=(B&&) = default;
// Exposed method of B
void B::my_func() const {
std::cout << "B::my_func" << std::endl;
pimpl->impl_my_func();
return;
};
// Implementation of A
class A::impl
{
public:
impl() {};
void impl_access_my_func(const A& a_in) {
std::cout << "impl_access_my_func" << std::endl;
a_in.my_func();
return;
};
};
// Constructor/Destructor of A
A::A() : pimpl{std::make_unique<impl>()} {};
A::~A() = default;
A& A::operator=(A&&) = default;
// Exposed method of A
void A::access_my_func() {
std::cout << "A::access_my_func" << std::endl;
pimpl->impl_access_my_func(*this);
return;
};
// Later in the main.cpp file
int main() {
// Make an object
A my_A_object;
my_A_object.access_my_func();
return 0;
};
Upvotes: 1
Views: 2275
Reputation: 26493
If you subclass A from B then, A should be able to call the interface of class B. It should not have to rely on its implementation.
The Pimpl-Ideom is just a way to deal with the limitations of C++, that you cannot split the declaration of private, protected and public parts of your class. Since you would not want to expose the private parts of your class to your class users and don't want to expose the protected parts to users who don't want to subclass, the Pimpl-Ideom moves these parts away from the header file.
To answer your question:
Upvotes: 1