0

重複の可能性:
純粋仮想関数にはインライン定義がない場合があります。なんで?

タイトル通り、なぜ?そして、(純粋ではない)仮想関数はどうですか?インライン形式にすることはできますか?そして、本当の理由を知りたいのです。ありがとう!

4

2 に答える 2

5

inlined関数ポインタが実行時にを使用して解決されるため、99%の確率で仮想関数を使用することはできませんvtable

仮想関数の目的は、サブクラスによってオーバーロードされることです。例 :

class A
{
    virtual int foo() { return 1; }
}

class B : public A
{
    virtual int foo() { return 2; }
}

int main(void)
{
    B b;
    A *a = &b;

    return a->foo();
}

main関数は1ではなく2を返します。

コンパイラが関数をインライン化すると、1が返されます。これは、コンパイラが仮定できるの*aはisAであり、ではないと仮定できるためBです。したがって、コンパイラは、のタイプを安全に想定できない場合、それを実行しません*a

この例では、コンパイラーは仮想化が不要であると正常かつ安全に想定する場合があります。これは、実際にはコンパイラーと最適化レベルに依存します。

場合によっては、コンパイラーは仮想化が不要であると安全に想定でき、そのような場合にのみinlineキーワードが意味をなします。

キーワードinlineで関数を宣言しても、関数がインライン化されない場合があります。

とにかく、inlineキーワードを手動で追加することはほとんどの場合良い考えではありません。今日のコンパイラは優れており、必要に応じて自動的にインライン関数になります。追加inlineすると、場合によってはパフォーマンスが低下する可能性があるため、悪用しないことをお勧めします

于 2013-01-02T13:08:41.733 に答える
2

まあ、純粋仮想関数は確かにインラインでマークすることができます。

struct Base
{
    virtual void Func() const = 0;
};

inline void Base::Func() const
{ std::cout<<"Base\n"; }

struct Concrete : Base
{
    virtual void Func() const;
};

inline void Concrete::Func() const
{ Base::Func(); std::cout<<"Concrete\n"; }

inlineまた、コンパイラーが呼び出す必要のある関数を静的に判別できる場合は、仮想関数をインライン化することができます(これはキーワードとはあまり密接に関連していません)。例えば:

int main(void)
{
    Concrete o;
    o.Func();
}

完全なデモ: http: //ideone.com/zlxn8I

そして、この関連する質問を参照してください:LTO、仮想化解除、および仮想テーブル

于 2013-01-02T13:16:21.423 に答える