3

私のC++プログラムでは:

#include<iostream.h>

class A
{
    public:
    virtual void func()
    {
         cout<<"In A"<<endl;
    }
};

class B:public A
{
    public:
    void func()
    {
        cout<<"In B"<<endl;
    }
};

class C:public B
{
    public:
    void func()
    { 
        cout<<"In C"<<endl;
    }
};  

int main()
{
    B *ptr=new C;
    ptr->func();
}

ステートメントはを呼び出す必要がありますB::func()。ただし、関数C::func()は呼び出されます。これに少し光を当ててください。'クラスA'で仮想キーワードが削除されると、これは発生しなくなります。

4

5 に答える 5

7

宣言された仮想関数は、すべての派生クラスで仮想になります(明示的に指定するかどうかは関係ありません)。したがって、func()は、A、B、およびCクラスで仮想的です。

于 2009-12-10T08:18:38.940 に答える
3

基本については、仮想関数に関するC ++ FAQLiteをお読みください。

仮想関数を使用すると、派生クラスで基本クラスによって提供される実装を置き換えることができます。コンパイラーは、オブジェクトが派生ポインターではなくベースポインターによってアクセスされる場合でも、問題のオブジェクトが実際に派生クラスのものである場合は常に、置換が常に呼び出されるようにします。これにより、ユーザーが派生クラスについて知らなくても、基本クラスのアルゴリズムを派生クラスで置き換えることができます。

于 2009-12-10T08:18:03.490 に答える
1

ステートメントはB::func()を呼び出す必要があります

ポインタはクラスのオブジェクトを指しているため、クラスCの関数を呼び出しますC

仮想関数は実行時バインディングにつながります。つまり、呼び出される関数は、コンパイル時に宣言されたポインターのタイプではなく、ポインターが指すオブジェクトに基づいて決定されます。

于 2009-12-10T08:20:00.450 に答える
1

これがポリモーフィズムの本質です。ptrmain関数は、が実際にクラスのオブジェクトを指していることを知る必要はありませんC。使用可能なインターフェイスが少なくともクラスで定義されているものであることを知る必要があります(これが、関数が必要な場合に、Bとして宣言する理由です)。B *ptrに固有のC、あなたがしなければならないでしょうC *ptr)。

関数がBで仮想であると言う場合、それはサブクラスによってオーバーロードされる可能性があることを意味し、コンパイラーはこの代替実装を探すコードを生成します。この場合、それを見つけてC(実際の詳細はコンパイラごとに異なる可能性がありますが、ほとんどのコンパイラはオブジェクトにテーブル、いわゆる仮想テーブルを運ばせ、func()特定の実装にマッピングします)、それを呼び出します。

仮想キーワードがない場合、これはコンパイラに代替実装がないことを通知し、それをB実装に直接ハードリンクします。

于 2009-12-10T08:20:49.710 に答える
0

あなたがやったとしたら:

B *obj = new B;

次に、B :: func()を呼び出します。
期待する機能を実現するには、Cでfuncの新しい実装を削除する必要があります。
仮想関数を使用する場合、同じファミリーのオブジェクトである限り、内部にあるオブジェクトのタイプがわからないと実際に言います(このAには、「家族」の「父」がいます。あなたが知っているのは、「家族」の各メンバーが特定の部分に対して異なる仕事をしなければならないということだけです。例えば:

class Father
{
public:
  virtual void func() { cout << "I do stuff"; }
};
class Child : public Father
{
public:
  virtual void func() { cout << "I need to do something completely different"; }
};

int main()
{
  Father *f = new Father;
  f->func(); // output: I do stuff
  delete f;
  f = new Child;
  f->func(); // output: I need to do something completely different
  delete f;
}
于 2009-12-10T08:41:00.160 に答える