虚函数,它是基类中的const而不是派生中的const

azp*_*are 8 c++ virtual inheritance const

任何人都可以解释以下代码的输出?

#include <iostream>
#include <string>
class Animal
{
public:
    Animal(const std::string & name) : _name(name) { }
    ~Animal() { }
    virtual void printMessage() const
    {
        std::cout << "Hello, I'm " << _name << std::endl;
    }

private:
    std::string _name;
    // other operators and stuff
};

class Cow : public Animal
{
public:
    Cow(const std::string & name) : Animal(name) { }
    ~Cow() { }
    virtual void printMessage()
    {
        Animal::printMessage();
        std::cout << "and moo " << std::endl;
    }
};

int main() {
    Cow cow("bill");
    Animal * animal = &cow;
    cow.printMessage();
    animal->printMessage();
}
Run Code Online (Sandbox Code Playgroud)

输出是

你好,我是账单
和moo
你好,我是账单

我不明白为什么.指针动物指向Cow类型的对象.printMessage是一个虚函数.为什么Cow类的实现不是被称为的?

Pet*_*der 13

Cow不会覆盖虚函数,Animal因为它具有不同的签名.什么是实际发生的情况是Cow隐藏的功能Animal.

这样做的结果是调用printMessage一个Animal将只使用版本Animal,不管Cow它是什么(它没有覆盖它),但调用它将Cow使用中的那个Cow(因为它隐藏了一个Animal).

要解决此问题,请删除constin Animal或添加constin Cow.

在C++ 2011中,您将能够使用override关键字来避免像这样的微妙陷阱:

class Cow : public Animal 
{ 
public: 
    Cow(const std::string & name) : Animal(name) { } 
    ~Cow() { } 
    virtual void printMessage() override
    { 
        Animal::printMessage(); 
        std::cout << "and moo " << std::endl; 
    } 
};
Run Code Online (Sandbox Code Playgroud)

注意添加overrideprintMessage().如果printMessage实际上没有覆盖基类版本,这将导致编译器发出错误.在这种情况下,您将收到错误.

  • 如果基类函数必须是const并且派生的函数必须是非const,你可以使用非虚拟接口惯用法,其中基函数不是虚拟的,但是调用非const的私有虚拟接口,因此可以是由派生类中的非const函数覆盖. (2认同)

Mar*_*som 6

你有两个不同的版本printMessage,一个是const一个,一个不是.这两者是无关的,即使它们具有相同的名称.新函数Cow隐藏了一个Animal,所以当你直接调用它时,编译器只考虑Cow版本.