How to derive from a pimpl class? - c++

Let's say the scenario is this.
IBase - interface.
BaseImpl - implementation.
BaseStub - allocates std::unique_ptr to BaseImpl named m_impl.
And then how to achieve the following?
IDerived - interface.
DerivedImpl - implementation, inherits from BaseImpl.
DerivedStub - allocates std::unique_ptr to DerivedImpl named m_impl, inherits from BaseStub.
It becomes a problem that BaseStub already allocates its implementation, and since DerivedStub does the same, it conflicts.
class IBase
{
public:
virtual void f1() = 0;
};
class IDerived
{
public:
virtual void f2() = 0;
};
class BaseImpl : public IBase
{
public:
virtual void f1() override {}
};
class DerivedImpl : public BaseImpl, public IDerived
{
public:
virtual void f2() override {}
};
class BaseStub : public IBase
{
public:
BaseStub() { m_impl.reset(new BaseImpl()); }
virtual void f1() override { m_impl->f1(); }
private:
std::unique_ptr<BaseImpl> m_impl;
};
// But this also creates BaseStub::m_impl.
class DerivedStub : public BaseStub, public IDerived
{
public:
DerivedStub() { m_impl.reset(new DerivedImpl()); }
virtual void f2() override { m_impl->f2(); }
private:
std::unique_ptr<DerivedImpl> m_impl;
};

Related

How to distinguish between two derived classes from base pointer, without repeatedly trying dynamic_cast<> or enum field

If i have a base class Base:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
};
And two derived classes:
class Derived1 : public Base
{
Derived1();
bool bar() override;
}
class Derived2 : public Base
{
Derived2();
std::vector<baz*> bazVector;
bool bar() override;
}
And i have a vector std::vector<Base*> mainVector which us populated like this:
mainVector.push_back(someDerivedPointer)
At some point i need to determine what object is stored: Derived1 or Derived2, so i could access Derived2->bazVector if object is Derived2
One solution is trying to dynamic_cast<Derived2>(mainVector.at(someIndex)) and check for returned nullptr, or storing some enum that would tell me what class this object belongs to, but these solutions seem crutchy, and i wonder if there is a better solution.
As advised in the comment section, you are probably looking the wrong direction.
There's high chance you are not tackling the problem with the right approach.
If you need to write different logic based on the actual derived class from a pointer, you are missing something.
We don't have too much details, but for what you said, you have two options:
1: adding a virtual method to retrieve your vector:
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual std::vector<baz*> getVector() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual std::vector<baz*> getVector() override {return {};};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual std::vector<baz*> getVector() override {return bazVector;};
}
2: insert the logic where you need this vector into a virtual function (this is probably the better):
class Base {
public:
bool foo;
virtual bool bar() = 0;
virtual ~Base() = default;
virtual void doSomething() = 0;
};
class Derived1 : public Base
{
public:
Derived1();
bool bar() override;
virtual void doSomething() override {/*no op*/};
}
class Derived2 : public Base
{
std::vector<baz*> bazVector;
public:
Derived2();
bool bar() override;
virtual void doSomething() override {/*do something with you bazVector*/};
}
The other answer is most likely the best way to go forward in OP's case, but considering how vague the question's title is, there is an alternative idiom that is sometimes useful when:
All the derived classes of Base are known ahead of time.
The derived classes are particularly heterogenous, and creating a lowest-common-denominator interface would be problematic in some way, shape, or form.
A good example of this would be an AST. clang's ASTConsumer uses a flavor of the technique.
The visitor. The basic idea is to have an external interface with virtual methods for each derived class, and have a single virtual function in Base that dispatches this to the correct function.
class Derived1;
class Derived2;
class Base {
public:
class Visitor {
public:
virtual void operator()(Derived1&) {}
virtual void operator()(Derived2&) {}
protected:
~Visitor() = default;
};
virtual void visit(Visitor& v) = 0;
virtual ~Base() = default;
};
class Derived1 : public Base
{
public:
Derived1(){}
void visit(Base::Visitor& v) override { v(*this); }
};
class Derived2 : public Base
{
public:
Derived2(){}
void visit(Base::Visitor& v) override { v(*this); }
};
// Usage example:
struct MyVisitor final : public Base::Visitor {
void operator()(Derived1& obj) override {
std::cout << "1\n";
}
void operator()(Derived2& obj) override {
std::cout << "2\n";
}
};
int main() {
std::vector<std::unique_ptr<Base>> bases;
bases.push_back(std::make_unique<Derived1>());
bases.push_back(std::make_unique<Derived2>());
MyVisitor v;
for(auto& b : bases) {
b->visit(v);
}
}

convert an object created with base class ctor to a derived class

I have the following classes:
class Base {
public:
virtual ~Base(){}
Base() {}
virtual void foo() = 0;
};
class Derived : public Base {
public:
virtual ~Derived(){}
Derived() : Base() {}
void foo() { printf("derived : foo\n"); }
};
class IInterface {
public:
virtual ~IInterface() {}
virtual void bar() = 0;
};
class C : public Derived, public IInterface {
public:
virtual ~C(){}
C() : Derived(){}
void bar() { printf("C : bar\n"); }
};
now I have a bunch of Derived* objects and I want to apply different interfaces on them :
Derived* d = new Derived();
C* c = dynamic_cast<C*>(d);
c->bar();
c->foo();
dynamic_cast returns nullptr and with c-style cast i get seg fault.
is there anyway to achieve this?
note that my objects are already created with Derived ctor.
i just want to treat them differently using Interfaces
The only way to achive this is to create a new object and move the data over from the old object.
Try encapsulating the behaviour that needs to change at runtime. Instead of inheriting from the IInterface, you have a member variable that is an IInterface pointer. Then instead of overriding bar in the child class, you pass the call to bar through to whatever is being pointed at. This allows modular behavior that looks just like polymorphism, but is more flexible:
class IInterface {
public:
virtual ~IInterface() {}
virtual void bar() = 0;
};
class Derived : public Base {
public:
IInterface* m_bar;
virtual ~Derived(){}
Derived() : Base(){}
void bar() {return m_bar->bar(); }
void foo() { printf("derived : foo\n"); }
};
You then derive and create IInterface objects and can associate any of them with Derived objects.

Implementing a class hierarchy properly

Say I have an interface hierarchy :
class A
{
virtual void commonFunc() = 0;
};
class B1 : public A
{
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
Interface A only exist to avoid duplicating the commonFunc() function.
Now if I want to implement this in order to have 2 instanciatable classes ImplB1 and ImplB2 i could do :
class ImplA
{
virtual void commonFunc();
};
class ImplB1 : public ImplA
{
virtual void b1SpecificFunc();
};
class ImplB2 : public ImplA
{
virtual void b2SpecificFunc();
};
The problem with this is that it makes ImplA instanciatable, which I don't want to. I only want ImplB1 and ImplB2 to be instanciatable, because ImplA is something asbtract that only exist to have the implementation of the common function in common.
How could i design this please ? Thank you.
Interface A only exist to avoid duplicating the commonFunc() function.
You certainly mean to avoid duplicating its declaration, don't you?
class ImplA
{
virtual void commonFunc();
};
This should probably be:
class ImplA : public A
{
virtual void commonFunc();
};
And I guess the point is that ImplA actually has an implementation of commonFunc. So for the sake of this answer's brevity, let's put it into the class definition:
class ImplA : public A
{
virtual void commonFunc() {} // implementation
};
The problem with this is that it makes ImplA instanciatable.
Just make ImplA's destructor pure virtual:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc() {}
};
This will prevent instantiation even inside of derived classes' functions. For example, the following will create a compiler error:
class ImplB1 : public ImplA
{
public:
virtual void b1SpecificFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
In fact, you will not even be able to instantiate the class in its own functions:
class ImplA : public A
{
public:
virtual ~ImplA() = 0 {}
private:
virtual void commonFunc()
{
ImplA a; // error, cannot instantiate abstract class
}
};
But seriously, this all seems pretty over-engineered. Perhaps what you really need is to make commonFunc a non-virtual protected function of A, which derived classes can then call if they need to.
Or perhaps commonFunc can just be a free-standing utility function?
You can do the following. Also, here is a SO question/answer about this.
Note: While I'm answering the question that you can do this I'm not asserting it's what you should do.
Code
#include <iostream>
class A
{
public:
virtual void commonFunc() = 0;
};
void A::commonFunc() // Pure virtual but implemented anyway
{
// Derived classes can explicitly opt-in to this implementation
std::cout << "A::commonFunc()\n";
}
class B1 : public A
{
public:
virtual void b1SpecificFunc() = 0;
};
class B2 : public A
{
virtual void b2SpecificFunc() = 0;
};
class ImplB1 : public B1
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b1SpecificFunc()
{
std::cout << "b1SpecificFunc()\n";
}
};
class ImplB2 : public B2
{
public:
// This function must be implemented because its declared pure virtual
virtual void commonFunc()
{
// Can override the behavior if desired...
A::commonFunc(); // Explicitly use default implementation
}
virtual void b2SpecificFunc()
{
std::cout << "b2SpecificFunc()\n";
}
};
int main()
{
//A a; // Won't compile (as expected/desired)
ImplB1 b1;
ImplB2 b2;
b1.commonFunc();
b1.b1SpecificFunc();
b2.commonFunc();
b2.b2SpecificFunc();
return 0;
}
Output
A::commonFunc()
b1SpecificFunc()
A::commonFunc()
b2SpecificFunc()

Would this be a valid way to implement pimpl that supports inheritance?

#include <iostream>
#include <memory>
#include <cstdlib>
class IBase
{
public:
IBase() = default;
virtual ~IBase() = default;
virtual void f1() = 0;
};
class IDerived
{
public:
IDerived() = default;
virtual ~IDerived() = default;
virtual void f2() = 0;
};
class BaseImpl : public IBase
{
public:
BaseImpl() = default;
virtual ~BaseImpl() override = default;
virtual void f1() override { /* serious code */}
};
class DerivedImpl : public BaseImpl, public IDerived
{
public:
DerivedImpl() = default;
virtual ~DerivedImpl() override = default;
virtual void f2() override { /* serious code */}
};
class Base : public IBase
{
public:
Base() : m_impl(std::make_shared<BaseImpl>()) {}
virtual ~Base() override = default;
virtual void f1() override { m_impl->f1(); }
protected:
Base(const std::shared_ptr<BaseImpl>& impl) : m_impl(impl) {}
std::shared_ptr<BaseImpl> m_impl;
};
class Derived : public Base, public IDerived
{
public:
Derived() : Base(std::make_shared<DerivedImpl>()) {}
virtual ~Derived() override = default;
virtual void f2() override { impl()->f2(); }
private:
std::shared_ptr<DerivedImpl> impl() { return std::dynamic_pointer_cast<DerivedImpl>(m_impl); }
};
int main()
{
Base base;
base.f1();
Derived derived;
derived.f1();
derived.f2();
std::cin.sync();
std::cin.get();
return EXIT_SUCCESS;
}
It works, but it looks so weird that I might just give up pimpl.
Imagine having your Base defined like this:
class Base {
public:
Base();
virtual ~Base();
virtual void f1();
protected:
class Impl;
Impl *p_impl; // or shared_ptr, or unique_ptr, or whatever you like.
};
Note that there is nothing defined of Base::Impl. This is a very important part of the PIMPL idiom as you might have to use elements in the Impl class that require #include-ing things you don't want to include in the header class.
The derived class would then look like this:
class Derived: public Base {
public:
Derived();
~Derived();
virtual void f1(); // or not, depends
virtual void f2();
protected:
class Impl2;
Impl2 *p_impl2; // note that Derived::Impl2 might inherit from Base::Impl
};
This still hides the implementation details of both Base and Derived in Base::Impl and Derived::Impl2, while giving you complete freedom to implement Derived in any way you like (including inheritance).
Your Impl classes should only contain private variables and methods.
Don't put anything that that need to be accessible from children class there. Sub-classing the Impl class is wrong way to go in C++ because that defeats the purpose of this pattern.

abc interface inheritance and re-exposing methods in base class

I am curious if there is a neat way to expose methods in the base class of a derived interface.
So in code: -
class cbase {
public:
void MyMethodA() { }
};
class cderived : public cbase {
public:
void MyMethodB() { }
}
class ibase {
public:
virtual void MyMethodA() = 0;
};
class iderived : public ibase {
public:
virtual void MyMethodB() = 0;
};
Now if I make cbase inherit ibase, and cderived implement iderived, the compiler will complain that when I instantiate cderived, MyMethodA() is abstract and not implemented.
MyMethodA() is implemented in the base class and through ibase. Is the only way to fix this to reimplement ibase's methods in the cderived class? If so, yuck!
So as below: -
class cbase : public ibase {
public:
void MyMethodA() { }
};
class cderived : public cbase, public iderived {
public:
void MyMethodA() { cbase::MyMethodA(); }
void MyMethodB() { }
};
cderived inst;
iderived *der = &inst;
der->MyMethodA();
der->MyMethodB();
ibase *bas = der;
bas->MyMethodA();
I hope this is enough to convey the question. :) It might sound a little loopy as we are trying to refactor old code.
I am sure there is plenty of eager commentary out there ;)
If I understand correctly you want to make ibase a virtual base class of iderived and cbase.
This was there is only one instance of each of your interface classes in the class hierarchy and when you join cbase and iderived together at the cderived level the non-virtual override of MyMethodA in cbase is used because it is the dominating override.
See here: Hidden Features of C++?
E.g.
class ibase {
public:
virtual void MyMethodA() = 0;
};
class iderived : public virtual ibase {
public:
virtual void MyMethodB() = 0;
};
class cbase : public virtual ibase {
public:
void MyMethodA() { }
};
class cderived : public cbase, public virtual iderived {
public:
void MyMethodB() { }
};
int main()
{
cderived inst;
iderived *der = &inst;
der->MyMethodA();
der->MyMethodB();
ibase *bas = der;
bas->MyMethodA();
}
Take a look into multiple inheritance.
The answer to that faq item is basically answer to your question :
class cderived : public virtual cbase {
public:
void MyMethodB() { }
}
class ibase {
public:
virtual void MyMethodA() = 0;
};
class iderived : public virtual ibase {
public:
virtual void MyMethodB() = 0;
};