C++ C++;多态性+;用于选择返回类型的模板成员函数。怎么做?
我想为对象分派实现一个类层次结构。不同的类分派不同的元素,每个类可以分派其表示为不同数据类型的元素 通过一个(错误的)例子可以更好地理解它。如果允许使用虚拟函数模板,我希望这样做:C++ C++;多态性+;用于选择返回类型的模板成员函数。怎么做?,c++,templates,virtual-functions,traits,C++,Templates,Virtual Functions,Traits,我想为对象分派实现一个类层次结构。不同的类分派不同的元素,每个类可以分派其表示为不同数据类型的元素 通过一个(错误的)例子可以更好地理解它。如果允许使用虚拟函数模板,我希望这样做: class Dispatcher { template <class ReturnType> virtual ReturnType getStuffAs(); }; 类调度器{ 模板 虚拟返回类型getStuffAs(); }; 这样我就可以实现子类,如下所示: class CakeD
class Dispatcher {
template <class ReturnType>
virtual ReturnType getStuffAs();
};
类调度器{
模板
虚拟返回类型getStuffAs();
};
这样我就可以实现子类,如下所示:
class CakeDispatcher : public Dispatcher {
template <>
virtual Recipe getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
};
class DonutDispatcher : public Dispatcher {
template <>
virtual Frozen getStuffAs(){ ... }
template <>
virtual Baked getStuffAs(){ ... }
}
class CakeDispatcher:公共调度程序{
模板
虚拟配方getStuffAs(){…}
模板
虚拟烘焙getStuffAs(){…}
};
类DonutDispatcher:公共调度程序{
模板
虚拟冻结getStuffAs(){…}
模板
虚拟烘焙getStuffAs(){…}
}
以便稍后我可以执行以下操作:
void function( Dispatcher * disp ) {
// Works for Donut and Cake, but result will be a different Baked object
Baked b = disp->getStuffAs<Baked>();
// works if disp points to a DonutDispatcher
// fails if it is a CakeDispatcher
// can be compiling/linking time error or runtime error. I don't care
Frozen f = disp->getStuffAs<Frozen>();
}
void函数(调度程序*disp){
//适用于甜甜圈和蛋糕,但结果将是不同的烘焙对象
烘焙b=disp->getStuffAs();
//如果disp指向DonutDispatcher,则此选项有效
//如果是CakeDispatcher,则失败
//可能是编译/链接时间错误或运行时错误。我不在乎
冻结f=disp->getStuffAs();
}
要求/限制:
- 所有可能的返回类型事先都不知道。这就是我“需要”模板的原因
- 每个类只能提供一些返回类型
- 类必须有一个共同的祖先,这样我就可以通过指向父类的指针存储对象,并通过该指针调用函数
- 编辑:我不能使用C++11功能,但我可以使用boost库
- 显然,虚拟模板功能
- :打破共同祖先的条件
- 使用某种类型的traits类包含子类的功能,但它不起作用,因为父类中的非虚拟实现无权访问此信息
class Dispatcher {
private:
typeid(?) childType;
public:
Dispatcher(typeid childT) : childType(childT) {}
// NOT VIRTUAL
template <class ReturnType>
ReturnType getStuffAs()
{
// or something equivalent to this cast, which I doubt is a correct expression
return dynamic_cast<childType *>(this)->childGetStuffAs<ReturnType>();
}
};
类调度器{
私人:
typeid(?)childType;
公众:
调度程序(typeid childT):childType(childT){
//不是虚拟的
模板
ReturnType getStuffAs()
{
//或者类似于这个角色的东西,我怀疑这是一个正确的表达
返回dynamic_cast(this)->childGetStuffAs();
}
};
然后子类将实现childGetStuffAs函数,这些函数也不是虚拟的。
我读过5-10个相关问题,但提供的解决方案似乎都不适合这个问题
你们谁能想出更好的解决办法?
是否有解决此问题的标准模式/技术
编辑:真正的问题
在实际问题中,我有一些物理模型,其属性可以用多种方式表示:函数、矩阵、概率分布、多项式和其他一些(例如,非线性系统可以表示为函数,但不能表示为矩阵,而线性系统可以转换为两者)
还有一些算法可以模糊地使用这些模型,但它们可能需要某些模型特征的特定表示。这就是“getStuffAs”函数的原因。整个想法有点复杂——这里解释得太多了——但我可以保证在这种情况下,接口定义得很好:输入、计算和输出
我的意图是,假设预先完全定义了可能的表示形式的数量,并使产品能够转换为无法修改的现有类型/类,使之成为可能。
然而,我开始意识到,用一种简单的方法来说,这确实是不可能的——我不想只为这个问题编写一个库。我的解决方案是循环模板和菱形继承的组合。 至少它起作用了。:)
#包括
类调度器
{
公众:
模板
T getStuff()
{
返回T();
}
};
模板
类填充器:公共调度程序
{
公众:
模板
TT getStuff(){
返回重新解释(本);
}
};
班级蛋糕{
公众:
蛋糕(){}
作废打印()
{
std::cout#包括
//作为类型标识符
结构材料{
虚拟void foo(){}
};
模板
struct stuff\u inh:stuff{
};
结构调度器{
模板
T*getStuffAs(){
返回(T*)((getStuffAsImpl(newStuff_inh()))));
}
虚拟void*getStuffAsImpl(void*)=0;
虚拟void type(){printf(“type::dispatcher\n”);}
};
结构蛋糕:公共调度程序{
void*getStuffAsImpl(void*p){
stuff*s=静态_铸造(p);
printf(“蛋糕impl\n”);
如果(动态_转换==NULL){
扔“坏石膏”;
}
退货(作废*)(新蛋糕());
}
虚拟void type(){printf(“type::Cake\n”);}
};
结构兔:公共调度程序{
void*getStuffAsImpl(void*p){
stuff*s=静态_铸造(p);
printf(“兔impl\n”);
如果(动态转换)!=NULL{
返回(无效*)(新兔子());
}
如果(动态_转换)!=NULL,则为else{
退货(作废*)(新蛋糕());
}
否则{
扔“坏石膏”;
}
}
虚拟void type(){printf(“type::Rabbit\n”);}
};
void foo(调度员*d){
d->getStuffAs()->type();
d->getStuffAs()->type();
}
int main(){
兔子*r=新兔子;
富(r),;
蛋糕*c=新蛋糕;
傅(丙),;
}
我不确定这个丑陋的解决方案是否正确,希望它能对您有所帮助。>\u template+virtua
#include <iostream>
class Dispatcher
{
public:
template<class T>
T getStuff()
{
return T();
}
};
template<class T>
class Stuffer : public Dispatcher
{
public:
template<class TT=T>
TT getStuff(){
return reinterpret_cast<TT>(this);
}
};
class Cake{
public:
Cake(){}
void print()
{
std::cout << "Cake" << std::endl;
}
};
class Recipe
{
public:
Recipe(){}
void print()
{
std::cout << "Recipe" << std::endl;
}
};
class CakeRecipe : public Stuffer<Cake>, public Stuffer< Recipe >
{
public:
};
int main()
{
Dispatcher* cr = reinterpret_cast<Dispatcher*>(new CakeRecipe());
cr->getStuff<Cake>().print();
cr->getStuff<Recipe>().print();
getchar();
return 1;
}
#include <cstdio>
// as a type identifier
struct stuff {
virtual void foo() {}
};
template <typename T>
struct stuff_inh : stuff {
};
struct Dispatcher {
template <typename T>
T* getStuffAs() {
return (T*)((getStuffAsImpl( new stuff_inh<T>() )));
}
virtual void* getStuffAsImpl(void*) = 0;
virtual void type() {printf("type::dispatcher\n");}
};
struct Cake : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("cake impl\n");
if (dynamic_cast<stuff_inh<Cake>*>(s) == NULL) {
throw "bad cast";
}
return (void*)(new Cake());
}
virtual void type() {printf("type::Cake\n");}
};
struct Rabbit : public Dispatcher {
void* getStuffAsImpl(void* p) {
stuff* s = static_cast<stuff*>(p);
printf("rabbit impl\n");
if (dynamic_cast<stuff_inh<Rabbit>*>(s) != NULL) {
return (void*)(new Rabbit());
}
else if (dynamic_cast<stuff_inh<Cake>*>(s) != NULL) {
return (void*)(new Cake());
}
else {
throw "bad cast";
}
}
virtual void type() {printf("type::Rabbit\n");}
};
void foo(Dispatcher* d) {
d->getStuffAs<Cake>()->type();
d->getStuffAs<Rabbit>()->type();
}
int main() {
Rabbit* r = new Rabbit;
foo(r);
Cake* c = new Cake;
foo(c);
}