C++ 中 operator= 的奇怪行为

Posted

技术标签:

【中文标题】C++ 中 operator= 的奇怪行为【英文标题】:Strange behaviour of operator= in C++ 【发布时间】:2020-08-01 03:48:09 【问题描述】:

我有一个基类 A 和两个派生类 B 和 C。B 定义了 = 运算符,以基类 A 作为参数。

在 B 类上调用 = 时,有时会调用基类 A 的运算符而不是 B 中的运算符。

class A 
        public:

        void operator=(A &) 
                printf("A =\n");
        ;
;

class B : public A 

        public:

        void operator=(A &s) 
                printf("B =\n");
        ;
;

class C : public A 
;

int main()

        B b1, b2;
        C c;

        b1 = b2;
        b1 = c;

输出是:

A =
B =

为什么第一个赋值没有调用 B::operator=()?

为什么第二个赋值也不调用 A::operator=(),因为它也是从 A 派生的?

我该怎么做才能让 B::operator=() 每次都被调用?

当我看到这个时,我感到非常惊讶。我注意到它只是因为我在 A 类中删除了 operator=() ("operator=() = delete"),导致编译器错误。

【问题讨论】:

B::operator= 是否应该使用A 而不是B 【参考方案1】:

您的B::operator= 不是复制赋值运算符。除了您提供的那个之外,还有一个隐式定义的复制赋值运算符,相当于

B& operator=(const B& other) 
  A::operator=(other);
  return *this;

此运算符不打印任何内容,但它调用基类上的赋值,并且打印A=

b1 = b2 调用此复制赋值运算符。 b1 = c 调用 B::operator=(A&),因为 C 不是 B

如果您希望调用您的运算符,请使用上面显示的签名定义一个复制赋值运算符,而不是其他重载。

【讨论】:

这完全有道理,谢谢。我尝试使用“B& operator=(const B&) = delete”来欺骗另一个 operator=(),但不幸的是这不起作用。但无论如何,拥有两个运营商并不是什么大问题。 声明为已删除的函数仍参与重载决议。如果它真的被选中,那么程序是不正确的。

以上是关于C++ 中 operator= 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

操作符重载operator

“operator !=”是不是应该在 C++ 中始终通过“operator ==”来实现?

C++中operator用法

C++中的迭代器

c++ new operator和operator new,delete operator和operator delete

C++,关于operator的详细总解,(原理和用法)