有人能为虚拟功能解释这种行为吗?

时间:2012-03-31 19:08:40

标签: c++ copy-constructor

我了解虚函数和运行时调用的基本概念。但我试过了 运行一些困扰我的代码

   class A {
   public:
    A& operator=(char) {
      cout << "A& A::operator=(char)" << endl;
      return *this;
    }
    virtual A& operator=(const A&) {
      cout << "A& A::operator=(const A&)" << endl;
      return *this;
    }
   };

   class B : public A {
   public:
      B& operator=(char) {
        cout << "B& B::operator=(char)" << endl;
        return *this;
      }

      virtual B& operator=(const B&) {
        cout << "B& B::operator=(const B&)" << endl;
        return *this;
      }
   };

   int main() {
    B b1;
    B b2;
    A* ap1 = &b1;
    A* ap2 = &b1;
    *ap1 = 'z';
    *ap2 = b2; 
   }

运行此程序会给我以下输出: -

   A& A::operator=(char)  //expected output
   A& A::operator=(const A&) //Why this Output?  in case of  *ap2 = b2;

b2B类型的对象,但仍然是虚拟A& operator=(const A&) 而不是虚拟B& operator=(const B&)。为什么会这样?

4 个答案:

答案 0 :(得分:3)

因为virtual B& operator=(const B&)未覆盖virtual A& operator=(const A&);论点不同。

答案 1 :(得分:2)

对于要覆盖基类函数的派生类函数,派生类函数需要具有完全相同的函数原型(例外:允许使用协变返回类型)。

派生类=中的B运算符在基类=中没有与A相同的函数原型,因此它不会覆盖基类{ {1}}。

唯一可用的=运算符是被调用的运算符。

答案 2 :(得分:2)

对于要被视为覆盖的函数,签名必须与基类中的版本完全匹配(好吧,如果返回指针或引用,则返回类型可能是协变的)。也就是说,您需要定义

B& B::operator= (A const&)

从基类覆盖版本。请注意,对于覆盖函数中的输入参数,协变是没有意义的,因为您无法保证仅使用基类在上下文中使用派生对象调用基类版本。如果覆盖函数的任何参数都可能是逆变的,但C ++不支持这一点。

答案 3 :(得分:2)

这里在派生类中,函数采用B而在基类中采用A.因此,基本上它不会被覆盖,因为函数参数是不同的。

  

另请注意,在覆盖的情况下,返回类型可能会有所不同,因为在您的情况下,您将返回基础中的A的引用和派生中的B的引用。   虚拟基地&amp; func(const Base&amp;)   虚拟衍生&amp; func(const Base&amp;)   这是覆盖

的有效形式