为什么派生类不使用基类运算符=(赋值运算符)?
Why doesn't a derived class use the base class operator= (assignment operator)?
下面是一个实际问题的简化版本。代码似乎不是调用Base::operator=(int)
,而是生成一个临时Derived
对象并复制该对象。为什么不使用基本赋值运算符,因为函数签名似乎完全匹配?这个简化的示例没有显示任何不良影响,但原始代码在析构函数中有一个副作用,会导致各种破坏。
#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 << "Startn";
Holder obj(1);
cout << "Finishn";
return 0;
}
输出为:
Start
Base()
Derived()
Base(int)
Derived(int)
~Derived()
~Base()
Finish
~Derived()
~Base()
http://ideone.com/TAR2S
这是
编译器生成的operator=
方法与成员函数隐藏之间的微妙交互。由于 Derived 类没有声明任何运算符 = 成员,因此编译器隐式生成了一个成员:Derived& operator=(const Derived& source)
。此运算符 = 在基类中隐藏了运算符 =,因此无法使用它。编译器仍然能够通过使用 Derived(int)
构造函数创建一个临时对象并使用隐式生成的赋值运算符复制它来完成赋值。
因为执行隐藏的函数是隐式生成的,而不是源代码的一部分,所以很难发现。
这可以通过在int
构造函数上使用 explicit
关键字来发现 - 编译器会发出错误,而不是自动生成临时对象。在原始代码中,隐式转换是一个常用的功能,因此没有使用explicit
。
解决方案相当简单,Derived 类可以从基类中显式拉入定义:
using Base::operator=;
http://ideone.com/6nWmx
相关文章:
- 重载Singly Linked List中的赋值运算符
- 使用赋值运算符重载从类中返回jobject
- 标准库类型的赋值运算符的引用限定符
- 复制构造函数、赋值运算符C++
- 标准::变体的赋值运算符
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- 基类和派生类的多态赋值运算符
- 为用户定义的类正确调用复制构造函数/赋值运算符
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 为什么初始化时没有调用重载赋值运算符?
- 赋值运算符重载和自赋值
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 重新赋值在运算符中不起作用 = 重载
- 我在 c++ 中的赋值重载运算符有什么问题?(包括详细信息)
- 初始化程序列表和赋值重载(运算符=)
- 在赋值移动运算符内部使用交换
- 复合赋值和运算符之间的区别
- LNK2019多级类层次结构中的纯虚拟赋值 (=) 运算符
- C++中奇怪的赋值/乘法运算符行为
- 在C++中为类创建赋值(=)运算符