2016-03-02 134 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 ; 
} 
相关问题