本文介绍了为什么派生类不使用基类operator =(赋值运算符)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是实际问题的简化版本.该代码似乎没有生成Derived临时对象,而是对其进行复制,而不是调用Base::operator=(int).由于函数签名似乎完美匹配,为什么不使用基本赋值运算符?这个简化的示例不会显示任何不良影响,但是原始代码在析构函数中具有副作用,会造成各种破坏.

Following is a simplified version of an actual problem. Rather than call Base::operator=(int), the code appears to generate a temporary Derived object and copy that instead. Why doesn't the base assignment operator get used, since the function signature seems to match perfectly? This simplified example doesn't display any ill effects, but the original code has a side-effect in the destructor that causes all kinds of havoc.

#include <iostream>
using namespace std;

class Base
{
public:
   Base()
   {
      cout << "Base()\n";
   }

   Base(int)
   {
      cout << "Base(int)\n";
   }

   ~Base()
   {
      cout << "~Base()\n";
   }

   Base& operator=(int)
   {
      cout << "Base::operator=(int)\n";
      return *this;
   }
};

class Derived : public Base
{
public:
   Derived()
   {
      cout << "Derived()\n";
   }

   explicit Derived(int n) : Base(n)
   {
      cout << "Derived(int)\n";
   }

   ~Derived()
   {
      cout << "~Derived()\n";
   }
};

class Holder
{
public:
   Holder(int n)
   {
      member = n;
   }

   Derived member;
};

int main(int argc, char* argv[])
{
   cout << "Start\n";
   Holder obj(1);
   cout << "Finish\n";

   return 0;
}

输出为:

Start
Base()
Derived()
Base(int)
Derived(int)
~Derived()
~Base()
Finish
~Derived()
~Base()

http://ideone.com/TAR2S

推荐答案

这是编译器生成的operator=方法与成员函数隐藏.由于Derived类未声明任何operator =成员,因此编译器将隐式生成一个成员:Derived& operator=(const Derived& source).此操作符= 隐藏操作符=在基类中,因此无法使用.编译器仍然可以通过使用Derived(int)构造函数创建一个临时对象并使用隐式生成的赋值运算符将其复制来完成赋值.

This is a subtle interaction between a compiler-generated operator= method and member function hiding. Since the Derived class did not declare any operator= members, one was implicitly generated by the compiler: Derived& operator=(const Derived& source). This operator= hid the operator= in the base class so it couldn't be used. The compiler was still able to complete the assignment by creating a temporary object using the Derived(int) constructor and copy it with the implicitly generated assignment operator.

因为执行隐藏的功能是隐式生成的,并且不是源代码的一部分,所以很难发现它.

Because the function doing the hiding was generated implicitly and wasn't part of the source, it was very hard to spot.

这可能是通过使用int构造函数上的explicit关键字发现的-编译器将发出错误,而不是自动生成临时对象.在原始代码中,隐式转换是一种常用的功能,因此未使用explicit.

This could have been discovered by using the explicit keyword on the int constructor - the compiler would have issued an error instead of generating the temporary object automatically. In the original code the implicit conversion is a well-used feature, so explicit wasn't used.

解决方案非常简单,Derived类可以从Base类显式提取定义:

The solution is fairly simple, the Derived class can explicitly pull in the definition from the Base class:

using Base::operator=;

http://ideone.com/6nWmx

这篇关于为什么派生类不使用基类operator =(赋值运算符)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:16