2

私はこのコードを持っています:

A * a = new A;
a->fun();
delete a;

a = new B;
a->fun();
delete a;

私がする必要があるのはそれを印刷させることです:

A::fun() //being printed by A's fun()
B::fun() //being printed by B's fun()

virtualキーワードを使用せずに。メインコードは変更しないでおく必要がありますが、クラスは変更できます。これはどのように行うことができますか?

(また、Bから派生A

4

3 に答える 3

3

これが教育目的であることを願っています。

のデストラクタがaそうでない場合、virtualこれは未定義の動作になります。したがって、デストラクタはである必要がありますvirtual

デストラクタがvirtualの場合は、を使用できますdynamic_cast。したがって、次のように変更できますA::foo

void A::fun()
{
   if ( dynamic_cast<B*>(this) )
       ((B*)this)->fun();
   else
       std::cout << "A::fun()";
}

非デストラクタを使用した代替virtual(呼び出した場合の未定義の動作delete):

struct A
{
        bool isA;
        A(bool isA = true) : isA(isA){};
        void fun();
};
struct B : A
{
        B() : A(false){}
        void fun() {cout<<"B::fun()"<<endl;}
};

void A::fun()
{
        if (isA)
                std::cout << "A::fun()"<<endl;
        else
                ((B*)this)->fun();
}
于 2012-09-27T11:32:26.487 に答える
0

クラスをAのインスタンスデータに格納し、すべてのコンストラクターに正しい値を設定させ、A :: fun()にそれをチェックさせ、適切にキャスト/リダイレクトさせるなど、面倒な作業を行うことができます。

または、仮想関数テーブルに相当するものを作成することもできます。以前と同じように、これはAのインスタンスデータの一部ですが、各クラスのコンストラクターによって入力されます。次に、A :: fun()は単にMyTable-> Fun()のようなことをします。

于 2012-09-27T11:32:44.700 に答える
0

このような何かがあなたを助けることができます。

class B;

class A
{
public:
   A() : instance(0) { }
   A(B* p): instance(p) { }
   virtual ~A() { }
   void foo();
private:
   B* instance;
};

class B : public A
{
public:
   B():A(this) { }
   void foo() { std::cout << "B::foo" << std::endl; }
};

void A::foo()
{
   if (!instance)
   {
      std::cout << "A::foo" << std::endl;
      return;
   }
   instance->foo();
}

http://ideone.com/Zd6cd

于 2012-09-27T11:46:10.327 に答える