#include<iostream>
class A {
public:
virtual bool isB() = 0;
};
class B : public A{
public:
B() { }
bool isB() {std::cout << " not B\n"; return true;}
};
class C : public A {
public:
C() { }
bool isB() {std::cout << " not B\n"; return false;}
};
int main() {
B b;
A& a = (b.isB()) ? a(B()) : a(C()); // here is the problem
}
I also tried to make it as static cast to pointer of child class but it seems to not work as well. In real code myfunction takes A reference as a parameter and the condition depends on other part of code.
CodePudding user response:
If I understand your question correctly, you want to create either a B
or a C
instance, depending on a.isB()
, where a
is a given reference to A
. a
can reference either a B
or a C
instance.
Creating an instance of B
or C
based on a
is easy:
if (a.isB()) {
B b;
} else {
C c;
}
The above code is not very useful. You want to have a valid A&
referencing the instance you just created. In C you cannot create a A&
and instantiate a derived object at the same time. Reference must always reference something that exists. So your code cannot work. Also, any reference to A that references either b
or c
existing after the if-statement will be a dangling reference: Once you exit the scope of either branch the instance gets destructed.
As a consequence, you would have to work with pointers, ideally smart pointers. You could write a function
std::unique_ptr<A> create(bool createB){
if (createB) {
return std::make_unique<B>();
}
else {
return std::make_unique<C>();
}
}
that returns an std::unique_ptr<A>
from a B
or C
instance, depending on the input variable createB
.
In your code, you could call it like this:
B b;
auto x = create(b.isB());
A& xref = *x;
Keep in mind, that the variable x
must outlive xref
. Otherwise xref
is a dangling reference and using it is undefined behavior.
Note that the function accepts a bool, not A const&
. I personally prefer this style, because the signature std::unique_ptr<A> create(A const& a)
does not properly convey the intent. I would be confused by this. If you have more than two derived classes, you could have create
accept an enum, where each value corresponds to a derived class.
Here is the full code: https://godbolt.org/z/EEqPMvhdE