虚拟赋值运算符C ++ [英] virtual assignment operator C++

查看:154
本文介绍了虚拟赋值运算符C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++中的赋值运算符可以是虚拟的。为什么需要它?我们可以让其他操作符也是虚拟的吗?

解决方案

赋值运算符不需要被虚拟。



下面的讨论是关于 operator = ,但它也适用于任何运算符重载的类型



下面的讨论表明,virtual关键字不知道关于找到匹配函数的参数的继承签名。在最后的例子中,它显示了如何在处理继承类型时正确处理赋值。






虚函数不知道参数的继承:



函数的签名需要是相同的,以便虚拟化。所以即使知道在下面的例子中,operator =也是虚拟的。该调用永远不会作为D中的虚拟函数,因为operator =的参数和返回值不同。



函数 B :: operator =(const B& right) D: :operator =(const D& right)是100%完全不同,看作是两个不同的函数。

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

int x;

};

D类:public B
{
public:
virtual D& operator =(const D& right)
{
x = right.x;
y = right.y;
return * this;
}
int y;
};








您可以定义一个虚拟函数,以便在分配给类型B的变量时可以为D设置默认值。这是即使你的B变量实际上是一个D存储到一个B的引用。你不会得到 D :: operator =(const D& right)函数。

在下面的情况下,存储在2 B中的2个D对象的赋值引用... D :: operator =(const B& right) code> override。

  //使用与上述相同的B 

class D:public B
{
public:
virtual D& operator =(const D& right)
{
x = right.x;
y = right.y;
return * this;
}


虚拟B& operator =(const B& right)
{
x = right.x;
y = 13; //默认值
return * this;
}

int y;
};


int main(int argc,char ** argv)
{
D d1;
B& b1 = d1;
d1.x = 99;
d1.y = 100;
printf(d1.x d1.y%i%i \\\
,d1.x,d1.y);

D d2;
B& b2 = d2;
b2 = b1;
printf(d2.x d2.y%i%i \\\
,d2.x,d2.y);
return 0;
}

列印:

  d1.x d1.y 99 100 
d2.x d2.y 99 13

这表明从不使用 D :: operator =(const D& right)



B :: operator =(const B& right)上没有虚拟关键字,如上所述,但y的值不会被初始化。也就是说它将使用 B :: operator =(const B& right)








您可以使用RTTI正确处理虚拟函数,类型。这是最后一个谜题,弄清楚如何在处理可能继承的类型时正确处理赋值。

  virtual B& operator =(const B& right)
{
const D * pD = dynamic_cast< const D *>(& right);
if(pD)
{
x = pD-> x;
y = pD-> y;
}
else
{
x = right.x;
y = 13; //默认值
}

return * this;
}


Assignment Operator in C++ can be made virtual. Why is it required? Can we make other operators virtual too?

解决方案

The assignment operator is not required to be made virtual.

The discussion below is about operator=, but it also applies to any operator overloading that takes in the type in question, and any function that takes in the type in question.

The below discussion shows that the virtual keyword does not know about a parameter's inheritance in regards to finding a matching function signature. In the final example it shows how to properly handle assignment when dealing with inherited types.


Virtual functions don't know about parameter's inheritance:

A function's signature needs to be the same for virtual to come into play. So even know in the following example, operator= is made virtual. The call will never act as a virtual function in D because the parameters and return value of operator= are different.

The function B::operator=(const B& right) and D::operator=(const D& right) are 100% completely different and seen as 2 distinct functions.

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

  int x;

};

class D : public B
{
public:
  virtual D& operator=(const D& right)
  {
    x = right.x;
    y = right.y;
    return *this;
  }
  int y;
};


Default values and having 2 overloaded operators:

You can though define a virtual function to allow you to set default values for D when it is assigned to variable of type B. This is even if your B variable is really a D stored into a reference of a B. You will not get the D::operator=(const D& right) function.

In the below case, an assignment from 2 D objects stored inside 2 B references... the D::operator=(const B& right) override is used.

//Use same B as above

class D : public B
{
public:
  virtual D& operator=(const D& right)
  {
    x = right.x;
    y = right.y;
    return *this;
  }


  virtual B& operator=(const B& right)
  {
    x = right.x;
    y = 13;//Default value
    return *this;
  }

  int y;
};


int main(int argc, char **argv) 
{
  D d1;
  B &b1 = d1;
  d1.x = 99;
  d1.y = 100;
  printf("d1.x d1.y %i %i\n", d1.x, d1.y);

  D d2;
  B &b2 = d2;
  b2 = b1;
  printf("d2.x d2.y %i %i\n", d2.x, d2.y);
  return 0;
}

Prints:

d1.x d1.y 99 100
d2.x d2.y 99 13

Which shows that D::operator=(const D& right) is never used.

Without the virtual keyword on B::operator=(const B& right) you would have the same results as above but the value of y would not be initialized. I.e. it would use the B::operator=(const B& right)


One last step to tie it all together, RTTI:

You can use RTTI to properly handle virtual functions that take in your type. Here is the last piece of the puzzle to figure out how to properly handle assignment when dealing with possibly inherited types.

virtual B& operator=(const B& right)
{
  const D *pD = dynamic_cast<const D*>(&right);
  if(pD)
  {
    x = pD->x;
    y = pD->y;
  }
  else
  {
    x = right.x;
    y = 13;//default value
  }

  return *this;
}

这篇关于虚拟赋值运算符C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆