C++ C++;模板:从基类调用派生模板类的成员函数
我目前正在开发一个电子表格应用程序,但我在模板方面遇到了问题。 模板的每个单元格都可以包含一个变量,该变量可以是任何标准类型 相关类是C++ C++;模板:从基类调用派生模板类的成员函数,c++,templates,inheritance,polymorphism,C++,Templates,Inheritance,Polymorphism,我目前正在开发一个电子表格应用程序,但我在模板方面遇到了问题。 模板的每个单元格都可以包含一个变量,该变量可以是任何标准类型 相关类是电子表格,其最重要的成员变量是SheetCells,它具有 键入vector。CellBase类是一个抽象类,CellField就是从中派生出来的 派生的,后者是存储恰好对应于一个单元格的一段数据的模板类 电子表格的一部分 我还有一个类,SheetView,它最终必须显示电子表格。(为了简单起见, 假设这个类拥有对其他所有类的完全访问权限。)这个类并不真正关心什么
电子表格
,其最重要的成员变量是SheetCells
,它具有
键入vector
。CellBase
类是一个抽象类,CellField
就是从中派生出来的
派生的,后者是存储恰好对应于一个单元格的一段数据的模板类
电子表格的一部分
我还有一个类,SheetView
,它最终必须显示电子表格。(为了简单起见,
假设这个类拥有对其他所有类的完全访问权限。)这个类并不真正关心什么类型
每个单元格的值都是,因为它无论如何都会将所有内容转换为字符串。然而,我的问题是写作
电子表格
的成员函数,返回包含数据的字符串。我的第一个想法是写一个函数
std::string SpreadSheet::getDataFromSheet(int行,int列)
将调用该函数
返回(std::to_string(SheetCells[row][column]->getData())
,其中getData()
是CellField
的成员函数,返回
属于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;
};
//电子表格
班级电子表格
{
私人:
内部高度,内部宽度;
公众:
电子表格(int-newHeight、int-newWidth);
~电子表格();
字符串getData(int行,int列);
载体<载体>细胞;
};
//牢房
类细胞库
{
公众:
CellBase();
虚拟~CellBase();
};
//CellField
模板
类别CellField:公共CellBase
{
公众:
CellField(T-newValue);
虚~CellField();
T getData();
T_值;
};
简而言之,我希望能够从电子表格
调用getData()
,但是后者的成员变量
仅包含指向CellBase
类的指针(但这些类实际上属于CellField
)
我已经研究过类似的问题,但它们似乎都没有解决基类成员函数调用模板
class
函数的问题,其中后者和前者需要返回T
类型的变量。也许<代码>空白>代码>指针会起作用?< /p> ,因为C++是强类型语言,不能直接调用它们,因为编译器不能计算函数的返回值是什么。
您需要做的是,将其全部映射到一个公共接口。你应该问的问题是:我真正需要从CelField那里得到什么信息?也许您只需要值的字符串表示,然后您可以执行以下操作:
class CellBase
{
virtual std::string getData()=0;
};
template<typename T>
class CellField : public CellBase
{
std::string getData(){//some implementation}
};
类CellBase
{
虚拟std::string getData()=0;
};
模板
类别CellField:公共CellBase
{
std::string getData(){//some实现}
};
另一个选项是使用
boost::any
,它可以包含您喜欢的任何类型。如果您不需要实际干扰返回值,而只需要将其传递给使用“任意参数”的其他函数,那么这一点尤其有用。但是,为了真正使用该值,您仍然必须使用boost::any_cast()
将其强制转换为特定类型,因此需要知道所需的类型,并在类型错误时进行适当的错误处理。一种可能的解决方案是雇佣访问者,具体如下:
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 ;
}
类访问者
{
虚拟~Visitor(void){}
虚拟无效访问(CellBase*cell){}
虚拟无效访问(CellBase*cell){}
...
} ;
类细胞库
{
公众:
CellBase();
虚拟~CellBase();
虚拟无效接受(访问者*v){v->visit(this);}
};
类DataGettServiceSitor:公共访问者
{
公众:
虚拟无效访问(CellBase*cell)
{
//在这里,我知道如何进行转换
}
虚拟无效访问(CellBase*cell){}
字符串文本;
} ;
字符串数据获取程序(CellBase*cell)
{
数据获取服务访问者;
单元格->接受(访客);
返回visitor.text;
}
许多可能的答案。。。我将使用虚拟纯函数“getData”,它返回一个boost::any,它允许您存储许多不同的类型这正是我所需要的。编译时没有错误并生成正确的结果。我建议使用override
关键字以防止将来出现问题(例如,通过重命名函数)