C++:函数重载和运算符的不同行为

3

我是C++的新手,正在学习中。 我有一个关于类函数重载的问题。

我有两个完全相同的代码,除了函数名称不同。 一个是普通函数,另一个是操作符重载。

#include <iostream>

using std::cout;
using std::endl;

class B;

class A {
  public:
    void test(A const &a) { cout << "AA" << endl; }
    void test(B const &b) { cout << "AB" << endl; }
};

class B : public A {
  public:
    void test(A const &a) { cout << "BA" << endl; }
};

int main() {
  B b1;
  B b2;
  b1.test(b2);
  return 0;
}

这个程序会打印出:
BA

这里有另一个程序。

#include <iostream>

using std::cout;
using std::endl;

class B;

class A {
  public:
    void operator=(A const &a) { cout << "AA" << endl; }
    void operator=(B const &b) { cout << "AB" << endl; }
};

class B : public A {
  public:
    void operator=(A const &a) { cout << "BA" << endl; }
};

int main() {
  B b1;
  B b2;
  b1.operator=(b2);
  return 0;
}

这个程序打印

AA

这两个程序唯一的区别就在于函数名:test和operator=。 我不理解为什么C++会像这样表现。 我有什么遗漏吗? 我正在使用Mac OS X 8.2下的g++ 4.2.1版本编译此程序。 谢谢!
1个回答

3
在你的第一个例子中,不是关于“overloading”的问题,在类“A”中的那两个“test”函数是重载,然而在类“B”和“A”中的“test”是“name hiding”,因为“B”重新定义了“test”。 “overloading”处理同一范围内的函数,“name hiding”则涉及到类层次结构。
b1.test(b2);

b2是类B的一个对象,B中的test函数需要类A的常量引用,在这种情况下是可以的,因此它将输出"BA"。

在第二个赋值运算符的情况下,您没有创建一个将B分配给B的赋值运算符,因此编译器为您创建了一个。由编译器创建的那个会调用A的赋值运算符。因此,打印出AA

如果在B中添加另一个operator=

void operator=(B const &B) { cout << "BB" << endl; }

由于在此情况下编译器不会为您生成赋值运算符,因此您将看到“BB”被打印出来。


请原谅,我可以再问一个问题吗? 当我将所有operator=变成虚函数,并创建一个指向A的指针变量ptr并将其设置为&b时,(*ptr).operator=(c); 将打印“AB”。 它的行为就像上面两种情况都不是。 为什么会这样呢? - lbyeoksan
@lbyeoksan 虚函数用于实现多态,即“一个接口,多个实现”。由于您将 b 分配给基类 A 的指针,因此它将首先搜索类 B 是否已为 B 定义了赋值运算符,由于您没有定义它,因此它将搜索基类的实现并找到带有 const B& 作为参数的实现,因此它将调用该实现。 - taocp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接