【发布时间】:2014-05-08 11:33:02
【问题描述】:
我需要创建类来表示表达式,例如someVar=2*(5+3)^5。为此,我想要以下课程:
class IExpression
{
public:
virtual ~IExpression( void ) { }
virtual CValue eval( const CScope & ) const = 0;
};
class CConstant : public IExpression
{
protected:
const CValue _value;
public:
virtual CValue eval( const CScope & ) const { return this->_value; }
};
class COperation : public IExpression
{
protected:
const IExpression * const _left;
const operator_e _eOper;
const IExpression * const _right;
public:
virtual ~COperation( void );
virtual CValue eval( const CScope & ) const;
};
class CVariable : public IExpression
{
protected:
const string _name;
public:
virtual CValue eval( const CScope & scope ) const { return scope.access( this->_name ); }
};
还假设我有一个类CScope,CVariable::eval() 使用它来访问变量:
class CScope
{
protected:
map<string, CValue> _mVars;
public:
inline const CValue & access( const string & name ) const;
inline CValue & access( const string & name );
};
我这里有问题。想象一下,我有一个使用运算符的操作,该运算符需要通过引用访问该值,以便可以设置它,例如= 或+=。对于我会做的任务:
CValue COperation::eval( const CScope & scope ) const
{
switch( this->_eOper )
{
// ...
case E_ASSIGN:
return this->_left->eval( scope ) = this->right->eval( scope );
}
}
这里的问题是this->_left->eval( scope ),其中_left 指向CVariable,将返回由该变量名称标识的CValue 的副本,并且分配不会进行上班。
我可以更改方法 eval() 的签名以使其返回 CValue &,但这会导致问题,因为在 COperation 的情况下,操作的结果是一个临时变量,它被销毁为COperation::eval() 返回。
你知道我该怎么做吗?
【问题讨论】:
-
您的作业的 LHS 允许哪些内容?只有变量还是某些类型的表达式?
-
这让我想起了圆椭圆问题:赋值是一种需要左操作数可变性的操作。也就是说,赋值不仅仅是一个操作,它有更严格的要求。
-
@dyp 在操作的左侧,允许 IExpression 的任何子类。如果你使用一个常量,它应该分配一个该常量的副本而不做任何事情,对于操作的结果也是如此,如果你使用一个变量,它应该分配一个对该变量的引用。至少这是我想做的。你认为我应该分开处理作业吗?
-
@ReCaptcha 不,我将 CScope 更改为 COperation。我写的时候搞错了。