5

継承ツリーのクラスの1つのコンストラクター内で、オブジェクトの最も派生したクラスを見つけようとしています。私は今これに数時間を費やしましたが、他にどのようにそれを行うことができるのか、なぜそれが意味をなさないのかについて途方に暮れています。それは完全に理にかなっているようですが、それでも機能しません。私はRTTIに関する多くのページを見つけましたが、基本的にどこにもありません。テストケースとその出力の後で説明を続けます。

起源:

#include <iostream>
#include <typeinfo>
#include <string>

class A
{
public:
  A(std::string foo);

  virtual void bar(A* a) = 0;
};

class B : public A
{
public:
  B();

  virtual void bar(A* a);
};

A::A(std::string foo)
{
  std::cout << "type as passed to A constructor: " << foo << " (" << this << ")" << std::endl;
  std::cout << "type as determined in A constructor: " << typeid(*this).name() << " (" << this << ")" << std::endl;
}

B::B() : A(typeid(*this).name())
{
  A* a = (A*)this;
  std::cout << "type as determined in B constructor: " << typeid(*a).name() << " (" << this << ")" << std::endl;
  this->bar(this);
}

void B::bar(A* a)
{
  std::cout << "type as determined in bar: " << typeid(*a).name() << " (" << a << ")" << std::endl;
}

int main()
{
  B b;
  b.bar(&b);

  return 0;
}

出力(g ++):

type as passed to A constructor: 1B (0x7fff5fbff910)
type as determined in A constructor: 1A (0x7fff5fbff910)
type as determined in B constructor: 1B (0x7fff5fbff910)
type as determined in bar: 1B (0x7fff5fbff910)
type as determined in bar: 1B (0x7fff5fbff910)

出力の2行目に、「1A」ではなく「1B」と表示させようとしています。まだ想像できない理由で、RTTIは「これ」から削除されていますか?それが仮想関数の概念を壊さないようにするにはどうすればよいでしょうか。(これまで知らなかったRTTIの一部を再実装していることに気付くまで、これを仮想関数で実装していました。)出力が示すように、「this」の使用を避ければ、これを機能させることができますが、設計上、破損しているように見えます。

4

3 に答える 3

4

関係するダイナミクスを誤解しているため、それを行うことはできません。

ルールは次のとおりです。

任意のクラスのthisinコンストラクタ/デストラクタは、それがコンストラクタ/デストラクタであるクラスを指します。

また、これが、コンストラクターで呼び出される関数が、動的ディスパッチを使用するときに関数が機能するvirtualことを通常期待するように動作しない理由です。virtual

コンストラクターが呼び出された後、を検出する必要があります。コンストラクターとデストラクタを除くすべてのメンバー関数で検出できます。

于 2012-06-20T05:49:16.420 に答える
3

期待される動作が見られます。コンストラクターの本体では、構築中のオブジェクトのタイプは、コンストラクターが実行されているクラスのタイプと同じであり、構築されている最も派生したクラスのクラスではありません。

typeid(*this)メンバー初期化式で使用される場合、異常は実際には式にあります。これは、C ++ 03では未定義の動作でしたが、C ++ 11で変更され、まだ構築されていない実際のオブジェクトの型ではなく、コンストラクターのクラスの型を取得できるようになりました。

于 2012-06-20T05:55:25.953 に答える
0

A継承関係を考えてみましょう。のコンストラクターが最初に実行され、次にwillのコンストラクターが実行されることをすでに知っているはずですB。のコンストラクター内ではA、オブジェクトはまだB構築されていないため、まだaではありません。したがって、コンストラクター内のオブジェクトの動的型は、常にクラス自体の型であり、派生クラスの型ではありません。デストラクタでも同じことが起こります。

一言で言えば、あなたがやりたいことは、建設時に行うことはできません。

于 2012-06-20T05:49:26.557 に答える