簡體   English   中英

C ++模板:從基類調用派生的模板類的成員函數

[英]C++ templates: Calling member function of derived template class from base class

我目前正在處理電子表格應用程序,但是模板存在問題。 模板的每個單元格都可以包含一個變量,該變量可以是任何標准類型。

相關的類是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>的成員函數,可以CellField<T>類型T 但是,由於SheetCells包含指向CellBase類的指針,我必須使getData成為CellBase的成員,但這是不可能的,因為我希望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;
};

簡而言之,我希望能夠從SpreadSheet調用getData() ,但是后者的成員變量僅包含指向CellBase類的指針(但這些類實際上是CellField<T>類型的)。

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

由於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>()將其轉換為特定類型,因此需要知道您期望的類型並在類型錯誤的情況下進行正確的錯誤處理。

可能的解決方案是雇用訪客,方法如下:

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 ;
}

暫無
暫無

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

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