簡體   English   中英

如何通過交叉廣播恢復接口

[英]How to recover an interface through crosscast

一等座

class Io_obj
{
public:
    virtual Io_obj* clone() const=0;
    virtual ~Io_obj(){}
};

一階派生類

template<typename T>
class Io : public Io_obj,T
{
public:
    Io(){}
    Io(string& s){cout << s << '\n';}
    Io* clone() const override {return new Io{*this};}
    static Io* new_io(string& s){return new Io{s};}
};

二等座

class Shape
{
public:
    virtual void draw() const=0;
    virtual ~Shape(){}
};

二次派生類

class Circle : public Shape
{
public:
    Circle(){}
    Circle(string& s){cout << s << '\n';}
    void draw() const override{cout << "draw circle\n";}
};

class Triangle : public Shape
{
public:
    Triangle(){}
    Triangle(string& s){cout << s << '\n';}
    void draw() const override {cout << "draw triangle";}
};

主要功能

using io_circle = Io<Circle>;
using io_triangle = Io<Triangle>;
using Pf = function<Io_obj*(string&)>;

map<string,Pf> io_map{{"circle",&io_circle::new_io},{"triangle",&io_triangle::new_io}};

Io_obj* get_obj(string& s){
    if(auto f=io_map[s]) return f(s);
    throw runtime_error{"error: wrong type"};
}

int main(){
    vector<string> vs{"circle","triangle","square"};
    for(auto x:vs){
        unique_ptr<Io_obj> my_obj{get_obj(x)};

        if(auto sp=dynamic_cast<Shape*>(my_obj.get())){
            sp->draw();
        }else{
            throw runtime_error{"error: bad cast"};
        }
    }
    return 0;
}

動態投射失敗。 看來由unique_ptr<Io_obj> my_obj{get_obj(x)}創建的對象的類型為Io_obj ,它沒有成員函數draw() 如何使其運作?

Bjarne Stroustrup的代碼:C ++編程語言Ch22.2.4

要解決此問題,請更改:

template<typename T>
class Io : public Io_obj, T

至:

template<typename T>
class Io : public Io_obj, public T

必須為每種基本類型分別編寫訪問說明符。 在您的情況下,第二個派生是private ,因為這是默認模式。

如果它們通過公共繼承創建的is-a關系連接, dynamic_cast<>會將Io<T> dynamic_cast<>轉換為T 在私有的情況下, dynamic_cast<>將不起作用,因為Io<T> 不是 T (私有繼承會創建稱為“根據...實現的”關系 )。

測試: http//coliru.stacked-crooked.com/a/130c7768fb5b501d

當然,此代碼還會拋出std::runtime_error ,因為您尚未為square類型注冊“ factory”,但我想您已經知道這一點了:)

可能有些參考( 18.5.2 - dynamic_cast<T>(v) ):

否則,將應用運行時檢查以查看v指向或引用的對象是否可以轉換為T指向或引用的類型。

運行時檢查在邏輯上執行如下:

如果,在最派生對象指向的(簡稱)至v ,V點(指)到的公共基類子對象T對象,並且如果只有一個類型的對象T從子對象衍生指出(簡稱)到v的結果是指向該T對象的指針(一個左值引用)。

否則,如果v指向(引用)最派生對象的公共基類子對象,並且最派生對象的類型具有類型T的基類(即明確且公共的) ,則結果為指針(表示左值)到最派生對象的T子對象。

否則,運行時檢查將失敗。

轉換為指針類型失敗的值是所需結果類型的空指針值。 轉換為引用類型失敗會拋出bad_cast

暫無
暫無

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

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