可以说我有一个抽象类,它的创建和复制非常昂贵:

class AbstractBase {
public:
    AbstractBase() {
        for (int i = 0; i < 50000000; ++i) {
            values.push_back(i);
        }
    }

    virtual void doThing() = 0;

private:
    vector<int> values;
};

它有两个子类FirstDerived:
class FirstDerived : public AbstractBase {
public:
    void doThing() {
        std::cout << "I did the thing in FirstDerived!\n";
    }

};

SecondDerived:
class SecondDerived : public AbstractBase {
public:
    void doThing() {
        std::cout << "I did the thing in SecondDerived!\n";
    }
};

此外,我想创建一个使用FirstDerivedSecondDerived通过组合(而不是聚合)的类。这意味着我希望ComposedOfAbstractBase拥有传入的任何临时项。如果我在此类中未使用抽象类,则该类将类似于:(在C++ 11中)
class ComposedOfWhicheverDerived {
public:
    ComposedOfWhicheverDerived(AbstractBase abstract_base) : abstract_base(std::move(abstract_base)) {;}
private:
    AbstractBase abstract_base;
};

但是,这不适用于抽象类,因为即使我小心不要传入临时AbstractBase,我也无法创建AbstractBase的实例,例如:
ComposedOfWhicheverDerived a(FirstDerived());

对于编译器来说,它就像:
ComposedOfWhicheverDerived b(AbstractBase());

因为我在类声明中仍然有AbstractBase的实例。

我想到的下一个解决方案是:
class ComposedOfAbstractBase {
public:
    ComposedOfAbstractBase(AbstractBase&& abstract_base) : some_derived_instance(abstract_base) {;}

private:
    AbstractBase& some_derived_instance;
};

这很完美(即使我不太了解)!这两个实例均有效,并且可以按预期工作:
ComposedOfAbstractBase a(FirstDerived());
ComposedOfAbstractBase b(SecondDerived());

它不会创建传入的AbstractBase临时副本的副本,并且允许存储对AbstractBase的引用。尽管充其量对一个右值引用的引用似乎还不清楚:它并不能传达ComposedOfAbstractBase拥有传入的任何临时文件。除此之外,事实证明该解决方案似乎不是最优的。为了显示这一点,我创建了此类:
class ComposedOfFirstDerived {
public:
    ComposedOfFirstDerived(FirstDerived first_derived) : first_derived(std::move(first_derived)) {;}

private:
    FirstDerived first_derived;
};

只能接受FirstDerived,因此我们可以应用std::move卸载临时文件的所有权。我可以这样创建一个实例:
ComposedOfFirstDerived c(FirstDerived());

有趣的是,此类的创建速度始终比ComposedOfAbstractClass高10%。

有人知道这是怎么回事吗?为什么ComposedOfFirstDerived的创建速度比ComposedOfAbstractBase这么快?有没有更好的方法来对抽象类进行合成,还是我陷入了次优的解决方案?

抱歉,这是一个满口的问题。感谢您抽出宝贵的时间阅读并给出真实的答案,因为我不为所动!

最佳答案

ComposedOfAbstractBase不是解决方案。您正在悬挂引用。

顾名思义,由于AbstractBase是抽象的-您不能按值保存一个。您只能按引用或指针保存一个。由于引用不能拥有该对象,因此将剩下指针。拥有指针的现代方式是使用unique_ptr:

class ComposedOfAbstractBasePtr {
public:
    ComposedOfAbstractBasePtr(std::unique_ptr<AbstractBase> p)
    : some_derived_instance(std::move(p))
    { }

private:
    std::unique_ptr<AbstractBase> some_derived_instance;
};

请注意,您的AbstractBase没有虚拟析构函数。你应该解决这个问题。

09-09 19:14