2015-11-08 99 views
2

第一基類的接口如何恢復通過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";} 
}; 

主要功能

​​

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

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

回答

3

爲了解決這個問題,更改:

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

到:

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

訪問符必須單獨爲每個被寫入基本類型。在你的情況下,第二個派生是private,因爲這是默認模式。

dynamic_cast<>Io<T>轉換到T,如果它們與連接是-一個關係,這是由公共inheritation創建。在私人情況下,dynamic_cast<>將不起作用,因爲Io<T>不是T(私有繼承創建的關係稱爲「按照」「實施)。

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

當然這段代碼也將引發std::runtime_error,如您尚未註冊「工廠」爲square類型,但我想你已經知道這一點:)

一些參考,也許(18.5.2 - dynamic_cast<T>(v)):

否則,運行時檢查被施加以查看是否指向的對象或 由v提及的參數可以轉換爲 的T指出的類型。

的運行時檢查邏輯的執行過程如下:

如果在最派生對象尖(簡稱),以通過v,V點 (指)的T公共基類子對象對象,並且如果僅 類型T的一個目的是從子對象派生指出 (簡稱),以通過v,其結果是一個指針(左值參照),以 該T對象。

否則,如果v點(指)到最派生對象的公共基類 子對象,和的派生對象的最 類型具有基類T類型的,即是無歧義和 public,結果是一個指針(一個左值指向)最大派生對象的T子對象。

否則,運行時檢查失敗。

指針類型失敗轉換的值是所需結果類型的空指針值 。失敗的演員參考類型投擲 bad_cast

+0

'dynamic_cast <>''將'Io '轉換爲'T'。如果我理解正確,在這個過程中'Circle'成爲'Io'的公共基礎。因此'Io'繼承'Circle'的成員函數'draw()'。由於在'Circle'的公共基礎'Shape'中'draw()'被聲明爲'virtual','sp-> draw()'的調用最終可以被編譯器處理。 –

+0

@MiloLu是的,就是這樣。雖然它沒有被編譯器處理。通常在運行時處理虛擬函數(我不考慮任何優化)以確定對象的實際類型(以及應該調用哪個虛擬函數)。 –

+0

我嘗試了一種不同的方法:將'T'作爲成員而不是公共基地,然後再次發佈問題。也許你可以有一些建議? http://stackoverflow.com/questions/33614524/how-to-cast-an-objx-to-an-x?noredirect=1#comment55004110_33614524 –