簡體   English   中英

C ++與抽象類的組合

[英]C++ Composition with abstract class

假設我有一個抽象類,創建和復制是昂貴的:

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的引用。 雖然充其量只是對rvalue引用的引用似乎不清楚:它沒有表明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沒有虛擬析構函數。 你應該解決這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM