8
class base {
public:
    void virtual fn(int i) {
        cout << "base" << endl;
    }
};

class der : public base{
    public:
    void  fn(char i) {
        cout << "der" << endl;
    }
};

int main() {

    base* p = new der;
    char i = 5;
    p->fn(i);
    cout << sizeof(base);
    return 0;
}

ここで、クラスで定義された関数fnのシグニチャは、関数名は同じですが、クラスで定義されたbase関数のシグニチャとは異なります。したがって、クラスで定義された関数はクラス関数を非表示にします。したがって、fnのクラス バージョンを呼び出しで呼び出すことはできません。それは結構です。fn()derderbasefn()derp->fn(i)

私のポイントは、なぜsizeofクラスなのbaseか、それともVTABLEポインターを使用しないのかということですder。ここでのVTABLEポインターの要件は何ですか?4

4

4 に答える 4

7

これは実装に大きく依存し、コンパイラごとに異なる可能性があることに注意してください。

の存在の要件vtableは、Baseクラスが継承と拡張を目的としていることであり、それから派生したクラスがメソッドをオーバーライドする可能性があります。

BaseクラスとDerivedクラスの2つは、異なる変換ユニットとコンパイラに存在する可能性がありますが、Baseクラスのコンパイルでは、メソッドがオーバーライドされるかどうかは実際にはわかりません。したがって、キーワードが見つかると、がvirtual生成されvtableます。

于 2012-02-02T09:13:33.897 に答える
1

vtableは通常、仮想関数に使用されるだけでなく、何かを実行するdynamic_castとき、またはプログラムがクラスのにアクセスするときにクラスタイプを識別するためにも使用されますtype_info

コンパイラが仮想関数がオーバーライドされておらず、他の機能が使用されていないことを検出した場合、最適化としてvtableポインタを削除する可能性があります。

明らかに、コンパイラーの作成者は、これを行うのに苦労する価値があるとは思っていません。おそらく、あまり使用されないためでありvirtual、基本クラスからを削除することで自分で実行できるためです。

于 2012-02-02T09:27:21.280 に答える
1

同じプロジェクトまたは別のプロジェクト内に次のものを含む別のソースファイルが存在する可能性があるため、コンパイラvtableは'base'クラスからメンバー変数を最適化できません。

struct ived : base {
    ived() : p(new char[BIG_DATA_SIZE]) {}
    virtual ~ived();
    virtual void fn(int);
private:
    char* p;
};

デストラクタは、fn他の場所に実装できます。

ived::~ived() { delete[] p; }

void ived::fn(int) {
    cout << "ived" << endl;
}

そして、別の場所のどこかに、次のようなコードが存在する可能性があります。

base* object = new ived;
ived->fn(0);
delete object;
cout << sizeof(base) << endl;

したがって、2つの問題があります。仮想関数ived::fnが呼び出されない、仮想デストラクタが呼び出されBIG_DATA_SIZEないため、削除されないということです。そうでなければ、sizeof(base)ここは異なります。そのため、コンパイラは常にvtable仮想メンバー関数または仮想基本クラスを持つクラスに対して生成します。

派生クラスでのデストラクタの呼び出しに関しては、必須と見なす必要があります。仮想関数を持つクラスがある場合、そのクラスも仮想デストラクタを宣言する必要があります。

于 2016-04-23T07:42:37.940 に答える
0

継承はis-a関係です。deris-a basebaseサイズがあり4der少なくともサイズがあり4ます。vftableptrのメンバーでありbase、のメンバーになりますder

baseには仮想メソッドがあるため、使用するかどうかに関係なく、仮想テーブルへのポインタがあります。

于 2012-02-02T09:18:08.413 に答える