1

基类特别声明该方法是非虚拟的。它适用于 Visual Studio 2008、2010 和 2012 以及ideone 使用的任何编译器(gcc 4.7+?)。

#include <iostream>

class sayhi
{
public:
    void hi(){std::cout<<"hello"<<std::endl;}
};

class greet: public sayhi
{
public:
    virtual void hi(){std::cout<<"hello world"<<std::endl;}
};


int main()
{
    greet noob;
    noob.hi(); //Prints hello world
    return 0;
}

这也有效 - 该方法在基类中是私有且非虚拟的:

#include <iostream>

class sayhi
{
private:
    void hi(){std::cout<<"hello"<<std::endl;}
};

class greet: public sayhi
{
public:
    virtual void hi(){std::cout<<"hello world"<<std::endl;}
};


int main()
{
    greet noob;
    noob.hi(); //Prints hello world
    return 0;
}

我的问题是:

  1. 合法吗?
  2. 为什么它有效?
4

3 回答 3

6

1. 合法吗?

的。

2. 为什么它有效?

没有什么可以阻止您在派生类中声明与基类的成员函数同名的成员函数。您在派生类中的函数将简单地隐藏基类的函数。顺便说一句,如果派生类中的函数恰好是virtual,那么子类可能会覆盖它:

class howdy : public greet
{
public:
    // Overrides greet::hi()
    virtual void hi() { std::cout << "howdy world" << std::endl; }
};

但是,这不会sayhi::hi()以任何方式影响:特别是,仅virtual在派生类中存在隐藏它的函数并不能使其成为 virtual. 因此,在通过指针或对基类实例的引用调用函数时,您不能期望虚拟调度起作用sayhi

sayhi noob;
noob.hi(); // Will NOT print "hello world"!

greet gentleman;
sayhi* p = &gentleman;
p->hi(); // Will NOT print "hello world"!

howdy neighbor;
p = &neighbor; 
p->hi(); // Will NOT print "howdy"!

greet* pG = &neighbor;
pG->hi(); // WILL print "howdy"!    
于 2013-02-26T23:42:52.553 回答
2

这是合法的。从那时起,该方法virtual在 的派生类中变为greet.

基类方法是隐藏的(就像非 发生的那样virtual)。

通过greet指针调用方法将动态解析调用。通过 a 调用它sayhi会静态地解决它。

举个例子:

class sayhi
{
public:
    void hi(){std::cout<<"hello"<<std::endl;}
};

class greet: public sayhi
{
public:
    virtual void hi(){std::cout<<"hello world"<<std::endl;}
};

class greetuniverse: public greet
{
public:
    virtual void hi(){std::cout<<"hello universe"<<std::endl;}
};

以下

sayhi* p = new greetuniverse;
p->hi();

将打印hello,因为hiis not virtual in sayhi。然而

greet* p = new greetuniverse;
p->hi();

将打印hello universe,因为该方法是动态调用的。

于 2013-02-26T23:42:41.813 回答
0

这是合法的。通过在派生类中命名一个函数 virtual ,您是在告诉编译器在运行时检查派生类的方法以在转到基类之前检查函数的实现。

于 2013-02-26T23:40:06.760 回答