Search code examples
c++referenceconditional-operator

How to create reference to an objcect and initialize it as a child class with conditinal operator?


#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.


Solution

  • 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