1

基本クラスは、メソッドが非仮想であることを明示的に宣言します。Visual Studio 2008、2010、2012、および使用するコンパイラのイデオン(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と、呼び出しが動的に解決されます。を介して呼び出すと、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ため、印刷されます。でもhisayhi

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

hello universeメソッドが動的に呼び出されるため、印刷されます。

于 2013-02-26T23:42:41.813 に答える
0

合法です。派生クラス virtual の関数に名前を付けることで、基本クラスに移動する前に関数の実装について派生クラスのメソッドをチェックするように実行時にコンパイラに指示します。

于 2013-02-26T23:40:06.760 に答える