c++ 如何创建对对象的引用,并使用条件操作符将其初始化为子类?

toiithl6  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(92)
#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
}

我也试过把它静态的转换成子类的指针,但是好像效果不太好。在真实的代码中,myfunction接受一个引用作为参数,条件依赖于代码的其他部分。

uurv41yg

uurv41yg1#

如果我没有理解错您的问题,您希望创建BC示例,具体取决于a.isB(),其中a是对A的给定引用。a可以引用BC示例。
基于a创建BC的示例非常简单:

if (a.isB()) {
    B b;
} else {
    C c;
}

上面的代码不是很有用。你想要一个有效的A&引用你刚刚创建的示例。在C++中你不能同时创建一个A&和示例化一个派生对象。Reference必须总是引用已经存在的东西。所以你的代码不能工作。另外,对A的任何引用(其引用存在于if语句之后的bc)将是悬空引用:一旦退出任一分支的作用域,示例就会被析构。
因此,你必须使用指针,最好是智能指针。你可以写一个函数

std::unique_ptr<A> create(bool createB){
    if (createB) {
        return std::make_unique<B>();
    }
    else {
        return std::make_unique<C>();
    }
}

它根据输入变量createBBC示例返回std::unique_ptr<A>
在您的代码中,可以这样调用它:

B b;
auto x = create(b.isB());
A& xref = *x;

请记住,变量x必须比xref存在,否则xref是一个悬空引用,使用它是未定义的行为。
注意这个函数接受一个bool,而不是A const&。我个人更喜欢这种风格,因为签名std::unique_ptr<A> create(A const& a)不能正确地表达意图。我会被这种方式搞糊涂。如果你有两个以上的派生类,你可以让create接受一个枚举,其中每个值对应一个派生类。
下面是完整的代码:https://godbolt.org/z/EEqPMvhdE

相关问题