2016-03-02 149 views
1

我目前正在處理電子表格應用程序,但我遇到了模板問題。 模板的每個單元格都可以包含一個可以是任何標準類型的變量。C++模板:從基類中調用派生模板類的成員函數

相關分類是SpreadSheet,其最重要的成員變量是SheetCells,它有 類型vector< vector<CellBase*> >CellBase類是一個抽象類,從中導出CellField<T>爲 ,後者爲存儲與電子表格的一個單元格 相對應的一段數據的模板類。

我有另一個課程,SheetView,最終必須顯示電子表格。 (爲了簡單起見, 假設這個類可以完全訪問其他類。)這個類並不關心每個單元格的值是什麼類型,因爲它會將所有內容都轉換爲字符串。但是,我的問題是編寫 成員函數SpreadSheet,它返回一個包含數據的字符串。我最初的想法是寫一個函數 std::string SpreadSheet::getDataFromSheet(int row, int column)SheetView會叫,然後該函數會做 return (std::to_string(SheetCells[row][column] -> getData())),其中getData()CellField<T>成員函數,returing 東西T型。 然而,由於SheetCells包含指向CellBase班,我必須做出getDataCellBase, 成員,但是這是不可能的,因爲我想getData()返回T類型的變量,同類型的模板類 CellField

所有類定義的相關部分如下。

//SpreadSheet 

class Spreadsheet 
{ 

private: 
    int _height, _width; 

public: 
    Spreadsheet(int newHeight, int newWidth); 
    ~Spreadsheet(); 
    string getData(int row, int column); 
    vector< vector<CellBase*> > SheetCells; 

}; 



//CellBase 

class CellBase 
{ 
    public: 
     CellBase(); 
     virtual ~CellBase(); 
}; 



//CellField 

template<typename T> 
class CellField : public CellBase 
{ 
    public: 
     CellField(T newValue); 
     virtual ~CellField(); 
     T getData(); 
     T _value; 
}; 

因此,在短期,我希望能夠調用getData()SpreadSheet,但後者 的成員變量只包含指向CellBase類(但這些類實際上CellField<T>類型)。

我已經看過類似的問題,但他們都沒有解決調用模板的基類成員函數class<T>函數,後者和前者需要返回類型爲T的變量。也許void*指針將工作?

+0

很多可能的答案......我會用純虛擬函數「的getData」,它會返回一個boost ::任何,它允許你存儲許多不同類型 – Garf365

回答

2

由於C++是一種強類型語言,您不能直接用這種方式調用它們,因爲編譯器將無法確定函數的返回值是什麼。

你需要做的是將其全部映射到一個通用接口。你應該問的問題是:我真的需要從CelField獲得什麼信息?也許你需要的是值的字符串表示,那麼你可以做這樣的事情:

class CellBase 
{ 
    virtual std::string getData()=0; 
}; 

template<typename T> 
class CellField : public CellBase 
{ 
    std::string getData(){//some implementation} 
}; 

另一種選擇是使用boost::any,這是能夠包含任何你喜歡的類型。如果您不需要實際干擾返回的值,而不是將它傳遞給採用「任意參數」的其他函數,那麼這非常有用。但是爲了真正使用該值,您仍然必須使用boost::any_cast<T>()將其轉換爲特定類型,因此需要知道您希望使用哪種類型,並在類型錯誤時進行適當的錯誤處理。

+0

這正是我所需要的。編譯沒有錯誤,併產生正確的結果。 – limitIntegral314

+0

我想建議使用'override'關鍵字來防止將來出現問題(例如,通過重命名函數) –

0

一個可能的解決方案是採用一個遊客,沿着這些線路:

Class Visitor 
{ 
    virtual ~Visitor(void) {} 
    virtual void visit(CellBase<int> *cell) {} 
    virtual void visit(CellBase<float> *cell) {} 
... 
} ; 

class CellBase 
{ 
public: 
    CellBase(); 
    virtual ~CellBase(); 
    virtual void accept(Visitor *v) { v->visit(this) ;} 
}; 

class DataGetterVisitor : public Visitor 
{ 
public: 
    virtual void visit(CellBase<int> *cell) 
    { 
     // here I know how to make the transformation 

    } 
    virtual void visit(CellBase<float> *cell) {} 
    string text ; 
} ; 

string dataGetter(CellBase *cell) 
{ 
    DataGetterVisitor visitor ; 
    cell->accept(visitor); 
    return visitor.text ; 
} 
相關問題