0

Essential c++ の章 5.10 ランタイム タイプの識別を読んでいるときに、問題が発生しました。最初に少し背景を紹介させてください。という名前の基本クラスとから派生しnum_sequenceたクラスがあります。基本クラスには名前付きの仮想関数があり、派生クラスには独自の定義があります。Fibonaccinum_sequencegen_elems

以下、本より​​。

Fibonacci fib;
num_sequence *ps = &fib;
ps->gen_elems(64);

gen_elems() の Fibonacci インスタンスが呼び出されることがわかっています。ただし、このテストから ps が Fibonacci クラス オブジェクトをアドレス指定することがわかっていますが、ps を介して gen_elems() の Fibonacci インスタンスを直接呼び出そうとすると、コンパイル時エラーが発生します。

ps->フィボナッチ::gen_elems(64); //コンパイル時エラーが発生する

ps は、それがアドレス指定するオブジェクトのタイプを知りません。たとえ、私たちと typeid および仮想関数メカニズムが知っていたとしてもです。

gen_elems() の Fibonacci インスタンスを呼び出すには、Fibonaccips型のポインターに変換するようにコンパイラーに指示する必要があります。static_cast と dynamic_cast の両方がこの仕事を行うことができます。

太字で迷っています。ps->gen_elems(64)のフィボナッチ インスタンスを実際に呼び出しますgen_elems()。static_cast と dynamic_cast を使用して、それをフィボナッチ型のポインターに変換する必要があるのはなぜですか?

4

1 に答える 1

4

ほとんどの場合、通常どおり仮想メソッドを呼び出し、ポリモーフィズムにその作業を任せて、必要に応じて最も派生した実装を呼び出します。著者が説明しようとしているのは、ポリモーフィズムを経ることなく、仮想メソッドの特定の実装を直接呼び出すことも可能であるということです。

クラスがから派生しFibonacciてオーバーライドgen_elems()を再度実行するとしますが、そのオーバーライドを呼び出したくない場合は、Fibonacciオーバーライドを呼び出します。num_sequenceコンパイル時にポインターをFibonacciポインター(または子孫ポインター)に変換することにより、コンパイラーがFibonccivtableにアクセスできるようになり、直接呼び出すコードを発行できるようになりますFibonacci::gen_elems()(実行時にポイントされるオブジェクトが実際にはFibanocciまたは子孫の場合、アプリがクラッシュ/破損する可能性があります。これはコンパイル時に検証できません)。

例えば:

class num_sequence
{
public:
    virtual void gen_elems(int value)
    {
        std::cout << "num_sequence" << std::endl;
    }
};

class Fibonacci : public num_sequence
{
public:
  void gen_elems(int value)
  {
        std::cout << "Fibonacci" << std::endl;
  }
};

class SomethingElse : public Fibonacci
{
public:
  void gen_elems(int value)
  {
        std::cout << "SomethingElse" << std::endl;
  }
};

num_sequence ns;
Fibonacci fib;
SomethingElse se;
num_sequence *ps;

ps = &ns;
ps->gen_elems(64); // displays "num_sequence"

ps = &fib;
ps->gen_elems(64); // displays "Fibonacci"

ps = &se;
ps->gen_elems(64); // displays "SomethingElse"

ps->Fiboacci::gen_elems(64); // compiler error!

static_cast<Fibonacci*>(ps)->Fibonacci::gen_elems(64); // displays "Fibonacci"
static_cast<SomethingElse*>(ps)->Fibonacci::gen_elems(64); // displays "Fibonacci"

Fibonacci *pfib = dynamic_cast<Fibonacci*>(ps);
if (pfib != NULL)
{
    pfib->gen_elems(64); // displays "SomethingElse"
    pfib->Fibonacci::gen_elems(64); // displays "Fibonacci"
}
于 2013-02-09T03:44:30.737 に答える