簡體   English   中英

兩個不同類的運行時多態性

[英]Runtime polymorphism for two different classes

我有兩個BY類,我無法按要求更改或編輯。 它們具有相同功能但具有不同名稱的功能。

我希望有一個通用的接口,在運行時根據一些輸入變量選擇類,如下面的代碼所述。 我不確定應該使用哪種設計模式。 如何創建WrapperYB類,根據創建的對象選擇Y::showB::showing

class A
{
public:
    A() {}
    virtual ~A();
    virtual void show() { cout << "show A" << endl;}
};


class B:A
{
public:
    B() {}
    virtual ~B();
    virtual void show() { cout << "show B" << endl;}
};



class X
{
    char m_i;
public:
    Y() {  m_i = 'X';}
    virtual void showing() { cout << "showing " << m_i   << endl;}
};

class Y:X
{
public:
    Y() {  m_i = 'Y';}
    virtual void showing() { cout << "showing " << m_i   << endl;}
};



class WrapperYB
{
    // to be implemented

public:
    explicit WrapperYB(const int& type);
    void show();

};

int main(){

    WrapperYB objY(1);

    objY.show(); // must call Y::showing

    WrapperYB objB(0);

    objB.show(); // must call B::show

}

如果您的編譯器支持C ++ 17 Standard,您可以使用std::variant嘗試此解決方案。 這與@Nicolas的答案中的解決方案類似,但variant將為您處理實現細節,不會使用動態內存分配,並支持其他內容,如復制和分配。

#include <variant>
#include <utility>
#include <type_traits>

class WrapperYB {
public:
    using variant_type = std::variant<Y, B>;

    template <typename... Args,
        std::enable_if_t<std::is_constructible_v<variant_type, Args...>>* = nullptr>
    WrapperYB(Args&& ... args) : m_variant(std::forward<Args>(args)...) {}

    variant_type& variant() noexcept { return m_variant; }
    const variant_type& variant() const noexcept { return m_variant; }

    void show()
    { std::visit(ShowImpl{}, m_variant); }

private:
    struct ShowImpl {
        void operator() (Y& y) const { y.showing(); }
        void operator() (B& b) const { b.show(); }
    };

    variant_type m_variant;
};

請參閱coliru上的完整工作示例。

您可以通過讓它包含std::unique_ptr<A>std::unique_ptr<X>來概括包裝器。

我提議這個:

#include <iostream>

using namespace std;

class A
{
public:
    A() {}
    virtual ~A() {}
    virtual void show() { cout << "show A" << endl;}
};


class B:A
{
public:
    B() {}
    virtual ~B() {}
    virtual void show() { cout << "show B" << endl;}
};

class X
{
protected:
    char m_i;
public:
    X () {  m_i = 'X';}
    virtual void showing() { cout << "showing " << m_i   << endl;}
};

class Y:X
{
public:
    Y() {  m_i = 'Y';}
    virtual void showing() { cout << "showing " << m_i   << endl;}
};

class WrapperYB
{
public:
    enum class Which { B, Y };

public:
    explicit WrapperYB (int n)
        : which(Which(n))
    {
        switch (which)
        {
            case Which::B: ptr.b = new B; break;
            case Which::Y: ptr.y = new Y; break;
        }
    }

    ~WrapperYB ()
    {
        switch (which)
        {
            case Which::B: delete ptr.b; break;
            case Which::Y: delete ptr.y; break;
        }
    }

    WrapperYB (const WrapperYB&) = delete;
    WrapperYB& operator = (const WrapperYB&) = delete;

public:
    void show()
    {
        switch (which)
        {
            case Which::B: ptr.b->show()   ; break;
            case Which::Y: ptr.y->showing(); break;
        }
    }

private:
    Which which;
    union {
        Y* y;
        B* b;
    } ptr;
};

int main(){

    WrapperYB objY(1);

    objY.show(); // must call Y::showing

    WrapperYB objB(0);

    objB.show(); // must call B::show
}

它不是“香草”設計模式,我不認為,更多的適配器和歧視聯合的組合。

請注意,無法復制或分配WrapperYB。

您可以將標准虛擬分派方法與抽象基本適配器類和所需的每個對象類型的子類一起使用。 使用工廠方法創建對象。

#include <memory>
//pre-defined structures Y, B
struct Y
{
    Y(){}
    ~Y(){}
    void show(){}
};

struct B
{
    B(){}
    ~B(){}
    void showing(){}
};

// Abstract adaptor base class. 
struct Adaptor
{
    virtual void show() = 0;
};

// A subclass of Adaptor for each type of object to be wrapped. 
struct Adaptor_Y: Adaptor
{
    Adaptor_Y(): y(){}
    void show() override
    {
        y.show();
    }
private:
    Y y;
};

struct Adaptor_B: Adaptor
{
    Adaptor_B(): b(){}
    void show() override
    {
        b.showing();
    }
private:
    B b;
};

// Factory method constructs the proper object and returns a pointer.
std::unique_ptr<Adaptor> get_adaptor(int flag)
{
    if(flag == 0)
    {
        return std::make_unique<Adaptor_B>();
    }
    else if(flag == 1)
    {
        return std::make_unique<Adaptor_Y>();
    }
    else throw std::runtime_error("Invalid flag value");
}

暫無
暫無

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

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