我有关于C++类继承的问题。
我有一个具有虚拟方法的类,例如:

class IFoo {
public:
    virtual int sayFoo() = 0;
};

我有几种实现,例如:
class Foo1: public IFoo {
public:
    virtual int sayFoo() {
        return 1;
    }
};

class Foo2: public IFoo {
public:
    virtual int sayFoo() {
        return 2;
    }
};

我想将IFoo实例保存在一个虚拟容器类(如某种包装器)中,以暴露IFoo的相同接口(interface):
class DummyWrapper : public IFoo {
public:
    DummyWrapper(IFoo& foo): foo{foo} {}
    virtual int sayFoo() {
        return foo.sayFoo(); //ALPHA
    }
private:
    IFoo& foo; //BETA
};

通常,一切都应该正常工作,例如,如下所示:
IFoo& foo = Foo1{};
DummyWrapper wrapper{foo};

wrapper.sayFoo();

我的问题是foo实际上只是一个r值,其作用域消失后就将其删除,例如:
DummyWrapper generateWrapper() {
    return DummyWrapper{Foo1{}};
}

这导致“ALPHA”行中出现读取问题。
一种解决方案是将r值放在堆上,并使用指针访问foo。由于我是C++的新手,也许我陷入了XY问题,所以我的问题是:
  • 这是唯一的解决方案吗?有没有更好的方法来解决问题?
  • 我认为我不能用IFoo foo替换“BETA”行,因为这样,DummyWrapper将始终存储IFoo的字节,而不是IFoo实现的字节。或者,也许我可以使用IFoo foo值来调用派生的虚方法?

  • 感谢您的任何答复

    最佳答案



    不幸的是,一旦涉及到多态性,是的,是的,不是,没有的。但是,如果使用智能指针,则可以得到与存储IFoo foo几乎等效的解决方案:

    // member:
    std::unique_ptr<IFoo> foo;
    
    // constructor:
    DummyWrapper(std::unique_ptr<IFoo>&& foo): foo(std::move(foo)) { }
    // need to accept r-value         ^
    // reference: std::unique_ptr is only movable, not copiable!
    // for the same reason, you need to preserve the r-value reference
    // on assignment to member...
    
    // creation of the wrapper:
    return DummyWrapper(std::make_unique<Foo1>(/* arguments for constructor, if there are */));
    



    绝对正确:这是一种称为“对象 slice ”的效果,在将派生对象分配给基对象的那一刻,所有来自派生类型的多余东西都会丢失。相当普遍的问题(例如,当人们尝试将派生对象存储在std::vector<Base>中时)。

    关于c++ - 在包装器中保存抽象值对象和继承的用法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56855441/

    10-11 22:38