0

以下代码进入无限循环。

#include <string>
#include <iostream>
using namespace std;

class A{
   public:
      A(){
         cout << "Normal constructor" << endl;
      }
      A(const A& moo){
         cout << "It's a constructor!" << endl;
         operator=(moo);
      }
      void operator=(const A& moo){
         cout << "Calling A::Operator=" << endl;
      }
};

class B : public A{
   public:
      B(){}
      B(const A& thea){
         cout << "Gotshere" << endl;
         operator=(thea);
      }
};


int main(){

   B b;

   b = A();

}

无限循环的输出在“Normal constructor”和“Gotshere”之间循环。我从main函数中猜测,在将 an 分配A给一个B类时,它会尝试调用B::operator=不存在的 ,因此它会B(const A&)再次调用。

我不明白为什么A()会被调用。有人知道吗?EDIT应该已经说清楚了,A()就是在无限循环上反复调用。

当然,解决方法是 put B::operator=(const A&),但我很想知道它为什么这样做。

此外,我为 class 添加了一个运算符B

void B::operator=(const A&) { cout << "That should fix things. A::Operator=" << endl; }

它确实解决了问题,但是当我这样做时B b; b = B(),我得到Calling A::operator=的不是 `B::operator=' 的输出。这是为什么?

4

2 回答 2

2

我不明白为什么调用 A() 。有人知道吗?

B继承A,所以在构造之前B,必须构造A组件。B由于您没有指定A要调用的构造函数,因此编译器会选择默认构造函数。

编辑(回应问题的编辑)

A反复调用部分而言,这就是您的逻辑错误的地方:您说

它尝试调用B::operator=不存在的 ,因此它再次调用 B(const A&) 。

但这不是正在发生的事情:它不是调用A' 运算符=,它调用的是编译器无偿为您生成的B' 运算符。=要验证,将行更改为A::operator=(thea);,无限递归将消失。

那么为什么要无限递归呢?回想一下,生成的赋值运算符的签名是

B& operator=(const B& b)

编译器需要一个 的实例B来传递给operator=,但您正在传递 的一个实例A。但是,您定义了一个构造B函数const A&。这足以让编译器通过创建临时 B、从 构造它const A&并调用 来产生正确的调用B::operator=,如下所示:

B temp(thea); <<== At this point, you're in an infinite recursion
B::operator=(temp);

附带说明一下,C++ 中的赋值是一个 lval,因此您的赋值运算符的重载应该通过引用返回被分配给的对象(即*this)。

A& operator=(const A& moo){
    cout << "Calling A::Operator=" << endl;
}
于 2012-05-26T04:30:39.477 回答
2

B::operator= 接受一个 B&,但你传递给它一个 A&,所以它必须从 A 构造一个新的 B,这会导致无限递归。

至于你的第二个问题。您定义了 B::operator=(const A &),但仍会自动生成采用 const B & 的赋值运算符,并且自动生成的赋值运算符调用基本赋值运算符。

于 2012-05-26T04:37:18.147 回答