我最近有一个C ++任务,我遇到了一个关于多态的问题。
我们需要将值存储在模板化的类中,该类继承自抽象接口类。
enum eOperandType {
Int8,
Int16,
Int32,
Float,
Double
};
class IOperand {
public:
virtual eOperandType getType() const = 0; // Type of the instance
virtual IOperand const *operator+(IOperand const &rhs) const = 0;
virtual ~IOperand() {}
};
template<typename T>
class Operand : public IOperand {
public:
Operand(T const &n, eOperandType type);
eOperandType getType() const;
IOperand const *operator+(IOperand const &rhs) const;
T const value;
eOperandType const type;
};
对于所有作业,我们被禁止编辑IOperand类,但可以自由使用我们需要的任何类。
稍后在代码执行时,数字被实例化,然后作为IOperand *存储在容器中。然后,我们获取此列表以操纵数字。
我的问题是找到如何将IOperand *转换为正确的操作数类型,以便操纵它并获得它的价值。
我尝试了一周的倍数方法,查看所有模板行为(当我尝试使用Operand<op.getType()>
并且T为枚举时触及墙壁)
我的实际设计是使用了很多开关:
switch (op.value->getType()) {
case Int8:
if (dynamic_cast<Operand<int8_t>*>(op.value.get())->value != dynamic_cast<Operand<int8_t>*>(stack.front().get())->value) {
throw RuntimeError("Assert failed. Whoopsie");
}
break;
case Int16:
if (dynamic_cast<Operand<int16_t>*>(op.value.get())->value != dynamic_cast<Operand<int16_t>*>(stack.front().get())->value) {
throw RuntimeError("Assert failed. Whoopsie");
}
break;
case Int32:
if (dynamic_cast<Operand<int32_t>*>(op.value.get())->value != dynamic_cast<Operand<int32_t>*>(stack.front().get())->value) {
throw RuntimeError("Assert failed. Whoopsie");
}
break;
case Float:
if (dynamic_cast<Operand<float>*>(op.value.get())->value != dynamic_cast<Operand<float>*>(stack.front().get())->value) {
throw RuntimeError("Assert failed. Whoopsie");
}
break;
case Double:
if (dynamic_cast<Operand<double>*>(op.value.get())->value != dynamic_cast<Operand<double>*>(stack.front().get())->value) {
throw RuntimeError("Assert failed. Whoopsie");
}
break;
default:
throw RuntimeError("wut");
break;
}
解决我问题的最佳清洁解决方案是什么?我需要在倍数位置和函数中“向下”我的值以操纵值,这里的断言代码只是其中许多其他的例子。
我可以在这里使用C ++ 14,但不能使用任何外部库。
答案 0 :(得分:0)
当我尝试使用带有T的操作数时,撞墙 枚举
模板在编译时进行评估。编译器为您使用的每种类型生成代码。像op.getType()
这样的动态值需要编译器在编译之后创建代码,这在JIT编译语言中肯定是可能的,但在C ++中则不行。
我担心你的问题没有'漂亮'的解决方案。您确实需要一种如您所示的切换语句,并根据getType()
的值来决定您的演员表。根据您的使用案例,虚拟功能可以帮助您,例如如果您想知道T
virtual size_t getSizeOf()
{
return sizeof(T);
}
但由于您不允许修改IOperand
,因此您仍然坚持使用您的解决方案。