我目前正在处理电子表格应用程序,但我遇到了模板问题。 模板的每个单元格都可以包含一个变量,该变量可以是任何标准类型。
相关的类是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>
的成员函数,撤退
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;
};
简而言之,我希望能够从getData()
调用SpreadSheet
,但后者的成员变量
仅包含指向CellBase
类的指针(但类实际上是CellField<T>
类型)。
我已经查看了类似的问题,但是它们似乎都没有解决调用模板class<T>
函数的基类成员函数的问题,后者和前者需要返回类型的变量T
。也许void*
指针会起作用吗?
答案 0 :(得分:2)
由于C ++是一种强类型语言,你无法通过这种方式直接调用它们,因为编译器无法弄清楚函数的返回值是什么。
您需要做的是将所有内容映射到一个通用界面。你应该问的问题是:我真正需要从CelField得到什么信息?也许您需要的只是值的字符串表示,然后您可以执行以下操作:
class CellBase
{
virtual std::string getData()=0;
};
template<typename T>
class CellField : public CellBase
{
std::string getData(){//some implementation}
};
另一种选择是使用boost::any
,它可以包含您喜欢的任何类型。如果您不需要实际干扰返回值,除了将其传递给其他任何参数&#34;任意参数&#34;之外,这一点尤其有用。但是,为了真正使用该值,您仍然必须使用boost::any_cast<T>()
将其强制转换为特定类型,因此需要知道您期望的类型,并在类型错误时进行正确的错误处理。
答案 1 :(得分: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 ;
}