Is it possible to use covariance alongside virtual inheritance?
Here is a simplified scenario.
class A{};
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
class CoreA
{
protected:
virtual A& Get() = 0;
};
class CoreB : public virtual CoreA {
virtual B& Get() = 0;
};
class CoreC : public virtual CoreA {
virtual C& Get() = 0;
};
class CoreD : public CoreB, public CoreC
{
public:
virtual D& Get() override { return d; }
protected:
D d;
};
I am running into an ambiguity problem due to both CoreB's and CoreC's Get functions. If they are removed, there are no more errors, but I need those Get functions.
I have been able to resolve the issue by renaming the Get functions inside of CoreB and CoreC, while overriding them in CoreD
class CoreB : public virtual CoreA {
virtual B& Get_B() = 0;
};
class CoreC : public virtual CoreA {
virtual C& Get_C() = 0;
};
class CoreD : public CoreB, public CoreC
{
public:
virtual D& Get_B() override { return d; }
virtual D& Get_C() override { return d; }
virtual D& Get() override { return d; }
protected:
D d;
};
Does anyone know of a cleaner workaround?
Reported Issue to Microsoft under Developer Community
Unfortunately, this is a limitation in MSVC’s object model and requires ABI breaking changes to support.
You can consider writing your own covariant wrapper to work around.
Related
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);
}
}
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.
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()
This is a simple question (I think). I'm just not sure about it and I'm looking for a good solution too :)
Let's say I have this:
class Base {
public:
virtual ~Base() {}
virtual Base& connect(Base &b) = 0;
}
class Derived: public Base {
public:
virtual ~Derived() {}
virtual Base& connect(Base &b)
{
// do_something
}
}
// Name is a class that is basically a String and assign it to any A or B object.
class A: public Derived {
public:
A(name N) { ... }
virtual ~A() {}
}
class B: public Derived {
public:
B(name N) { ... }
virtual ~B() {}
A& connect(A &a)
{
// do something else
}
}
int main(int argc, char *argv[])
{
A objA("A");
B objB("B");
// Here's where is my issue
objB.connect(objA);
}
When I call objB.connect(objA), it is actually calling Base& connect(Base &b). I understand because both are child of Base and both have connect() defined in Derived. But the thing is that I would like that whenever I have objB.connect(objA), it should call A& connect(A &a) instead.
I would like to know if there is a way to have it the way I want.
Thanks :)
UPDATE
I edited this, because I had several typos. I didn't copy-paste the code, because it is quite more complex than I wish >.< Hope it is enough.
Your code won't compile. Here is code that compiles and result is as you desire: you can choose which version of connect to call based on a pointer type:
class Base {
public:
virtual ~Base() {}
virtual Base& connect(Base &b) = 0;
};
class Derived: public Base {
public:
virtual ~Derived() {}
virtual Base& connect(Base &b)
{
qDebug() << "Baseconnect";
}
};
class AA: public Derived {
public:
AA() {}
virtual ~AA() {}
};
class BB: public Derived {
public:
BB() {}
virtual ~BB() {}
AA& connect(AA &a)
{
qDebug() << "Aconnect";
}
};
example:
int main(int argc, char *argv[])
{
AA* aaptr = new AA;
BB* bbptr = new BB;
bbptr->connect(*aaptr); // version from BB is called
Derived* dptr = new BB;
dptr->connect(*aaptr); // version from Derived is called
// ...
}
As a side note, please always ensure that your code compiles and question is well defined. You narrow down the chances for helpful answer to your question otherwise.
it's pretty diffecult for me to describe my problem.
I have two classes, I would say Base_A and Derived_A. You can see from the names, the class Derived_A is derived from Base_A. Also in my program I have other two classes Base_B and Derived_B (also with inheritance). The class Base_A contains the object of Base_B, and the class Derived_A contains the object of Derived_B.
class Base_A {
public:
Base_A() {}
virtual ~Base_A() {}
Base_B b_;
Base_B* pointer_;
void init() {
b_ = Base_B();
pointer_ = &b_;
pointer_->setValue(1);
}
void print() {
pointer_->getValue();
}
};
class Derived_A: public Base_A {
public:
Derived_A() {}
virtual ~Derived_A() {}
Derived_B b_;
Derived_B* pointer_;
void init() {
b_ = Derived_B();
pointer_ = &b_;
pointer_->setValue(2);
pointer_->increaseValue();
}
};
class Base_B {
public:
Base_B() {}
virtual ~Base_B() {}
int value_;
void setValue(int value) {
value_ = value;
}
void getValue() {
cout << "Base_B: " << value_ << endl;
}
};
class Derived_B: public Base_B {
public:
Derived_B() {}
virtual ~Derived_B() {}
void increaseValue() {
value_++;
}
};
int main() {
Derived_A derived_A = Derived_A();
derived_A.init();
derived_A.print();
return 0;
}
How you can see every class of A has one object of class B and pointer to this object. My problem is, when I call the function print(), it does not take Derived_B* pointer_, but try to access Base_B* pointer_, which is not exist. How I can say in my program, that it should take the pointer according to the class? Or do I need to declarate the Base_B* pointer_ inside the Derived_A class like:
Base::pointer_ = pointer_;
Maybe is there other method or algorithm for my problem?
Thank you a lot.
"but try to access Base_B* pointer_, which is not exist"
If DerivedA does not properly initialise BaseA, then DerivedA does not meet the "isA" rule for inheritance and the design needs changed. On the face of things:
Don't re-use names in the derived class such as b_, pointer_.
Its just confusing and you gain no value.
Make init() virtual.
Have DerivedA::init() call BaseA::init() explicitly.
Make pointer_ a virtual method.
Note the use of "covariant return types" for the virtual methods.
class BaseA
{
public:
virtual BaseB* pointer() { return &b_; }
// etc.
};
class DerivedA : public BaseA
{
public:
virtual DerivedB* pointer() { return &b_; }
// etc.
};
wouldn't Base_A have a pointer to Base_B if Base_A::init() was ever called?
why wouldn't you init the base class?