为什么必须在运算符重载中提供关键字const

时间:2010-06-01 13:09:53

标签: c++ c visual-studio visual-studio-2008 visual-c++

只是好奇为什么param必须是操作重载的const

CVector& CVector::operator= (const CVector& param)
{
  x=param.x;
  y=param.y;
  return *this;
}
你能不能轻易做到这样的事情?

CVector& CVector::operator= (CVector& param) //no const
{
  x=param.x;
  y=param.y;
  return *this;
}

当某些东西变成const时,它对于应用程序生命的其余部分是不可改变的?这在操作重载方面有何不同?

7 个答案:

答案 0 :(得分:8)

您不需要const:

  

@ numerical25:只是好奇为什么param必须是操作重载的const

这不是必需的,但这是一个很好的设计决定。

参见C ++标准第12.8-9节:

  

用户声明的副本分配   operator X :: operator =是一个非静态的   类的非模板成员函数   X只有一个类型的参数   X,X&,const X&,volatile X&或const   易变的X&


我认为这是一个好主意:

使用const参数对我来说似乎是一个逻辑设计决定,因为你想确保不会改变其他值。

它告诉其他人使用您的课程,当您说出other之类的内容时,您不会更改myObject = other;值,并强制执行此操作,以免意外更改other }。

此外,如果您允许对象的非常量引用作为参数,那么您将限制可以使用您的函数的对象数量。如果它是const,它可以用于const和非const的参数。如果您的参数是非const,则它只能由非const的参数使用。


const仅适用于当前引用,而不适用于对象:

  

@ numerical25:当某些东西变成一个const时,它对于应用程序生命的其余部分是不可改变的?这在操作重载方面有何不同?

const引用只是一个const引用。它不会改变您传入的实际对象的常量。


非const运算符重载的示例:

以下是运算符重载的示例,其中参数不是const 我不建议做这件事:

class B
{
public: 
 const B& operator=(B& other)
 {
  other.x = 3;
  x = other.x;
  return *this;
 }

 int x;
};


void main(int argc, char** argv[])
{
 B a;
 a.x = 33;
 B b;
 b.x = 44;
 a = b;//both a and b will be changed
 return 0;
}

答案 1 :(得分:2)

const参数在使用它的整个函数中都是const,它不会在它之外改变它的常量。

在这种情况下,您需要声明一个const参数,以便赋值运算符接受非const变量和const变量;特别是后一种情况,包括表达式的结果,这是一个临时的const变量,你通常希望在赋值中支持它。

答案 2 :(得分:1)

如果您使用

CVector& CVector::operator= (CVector& param) // no const

然后做了这个:

const CVector& my_vector = GetMyVector();
some_other_vector = my_vector; // call assignment operator - error!

您将收到错误,因为my_vectorconst CVector&且无法转换为CVector&(非const引用)。它只是operator=函数中const的局部引用,而不是整个对象本身。

答案 3 :(得分:1)

你可以使用非常数变种,但这有两个反响,一个是功能性的,一个是关于你作为函数的作者告诉用户的内容。

1)调用带有非const引用的函数的人将无法使用const变量调用它

2)当你有一个非const引用的函数参数时,你发出信号,“我保留改变它的权利”。通常,当您的函数的用户写a = b;时,他不希望b改变。

请注意,您可以使用第三个选项,即按值传递:

CVector& CVector::operator= (CVector param) //no reference

这没有我上面提到的任何问题。但是,效率非常低。由于这三个因素,通过引用到const是首选,尤其是在像复制可能很昂贵的向量的情况下。

答案 4 :(得分:0)

出于同样的原因你可以在任何地方使用const:确保将来对方法的更改不会无意中修改传入的参数,以帮助记录接口通知调用者传递param是安全的而没有它的风险更改,并允许调用者传入在调用代码中声明为const的引用。

答案 5 :(得分:0)

另一个原因是允许转换。例如:

string s = "foo";
s = "bar";

这里,实现可能选择仅提供赋值运算符,该赋值运算符将字符串的const引用作为参数,并依赖编译器使用构造函数从char *“bar”创建临时字符串。如果op ='s参数不是const,这将无效,因为您无法将临时绑定到非const引用。

答案 6 :(得分:0)

const限定符使传递的参数(在您的示例中为'const CVector& param')为只读。 const限定符确保在operator =()方法中不更改参数(param)。

如果没有const限定符,可以使用以下命令:

CVector& CVector::operator= (CVector& param)
{
  x=param.x;
  y=param.y;

  param.x = 10; // some random value
  param.y = 100;

  return *this;
}

上述方法在将值赋给左侧操作数后改变右侧操作数'param'。 const限定符可以帮助您不违反赋值操作的语义。