2011-01-24 23 views
2

抽象クラスが存在するところでメソッドオーバーライドを正しく処理することに問題があります。 クラス階層内にあります。 私が説明しようとするでしょう:抽象クラスでのC++と継承

class AbstractClass{ 
public: 
    virtual void anyMethod() = 0; 
}; 

class A : public AbstractClass { 
    void anyMethod() { 
     // A implementation of anyMethod 
     cout << "A"; 
    } 
}; 

class B : public AbstractClass { 
    void anyMethod() { 
     // B implementation of anyMethod 
     cout << "B"; 
    } 
}; 

AbstractClass *ptrA, *ptrB; 

ptrA = new A(); 
ptrB = new B(); 
ptrA->anyMethod(); //prints A 
ptrB->anyMethod(); //prints B 

Ok..previous例の作業罰金.. AbstractClass 方法anyMethodの具体的な実装は、実行時に呼び出されます。 しかしAbstractClassはanyMethod呼ば 仮想ではない方法であり、他の基本クラスから派生している:私は何を誤解してい

ptrA = new A(); 
ptrB = new B(); 
ptrA->anyMethod(); //prints OtherClass 
ptrB->anyMethod(); //prints OtherClass 

:私はそのような何かをしようとすると、今

class OtherClass { 
public: 
    void anyMethod() { 
     cout << "OtherClass"; 
    } 
}; 

class AbstractClass : public OtherClass { 
public: 
    virtual void anyMethod() = 0; 
}; 

//A and B declared the same way as described before. 

を? キャストやtypeidなどを使わずにptrAとptrBの印刷AとBを作成するソリューションはありますか?

+0

コードをフォーマットしてください – Elalfer

+3

AとBも同様に2番目のケースに印刷してください。あなたの説明から何かが欠けていますか? – vitaut

+3

私はあなたのコードをg ++でテストし、どちらの場合でもAとBを表示します。万一、 'OtherClass *'を使っていますか? – casablanca

答えて

0

答えに感謝します。私は問題を理解するのを助けました。 実際の問題を誤解していたので、間違ったコードを投稿しました。 とにかく、私は私の問題を部分的に解決したと思います。 ここでは、コードです:

#include <iostream> 

`` using namespace std; 

class Other{ 

public: 

void foo(){ 
     cout << "Other\n"; 
} 

void foo(int a){} 
}; 

class Abstract : public Other{ 

public: 
virtual void foo() {}; 
virtual void foo(int c){ 
     Other::foo(c); 
} 
}; 

class A : public Abstract{ 

public: 

void foo(){ 
     cout << "A\n"; 
} 
}; 

class B : public Abstract{ 

public: 

void foo(){ 
     cout << "B\n"; 
} 
}; 
int main(){ 

cout << "main\n"; 

Abstract * ptrA = new A(); 
Abstract * ptrB = new B(); 

Other *o = new Other(); 
o->foo(); 

ptrA->foo(); 
ptrB->foo(); 
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract 
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base 

私は2つのエラー作っていた:私の実際のコード(前に投稿されていません簡易版)では

  1. を私は 仮想関数fooを宣言するのを忘れて()

  2. は、
  3. 仮想宣言でさえ十分ではありませんでした。実際には、その関数のすべての実装は、サブクラスAおよびBから見えるようにAbstractクラス内にラップする必要があります。それ以外の場合はコンパイルしないでください。

私はそれがクリーンな解決策になりうるかどうかわかりません。実際、私はすべてのfooメソッドのシグネチャをラップする必要があります。

2

anyMethodがいるあなたはポインタまたは参照を持つように、基本クラスに仮想宣言された場合は、それ正しく事実見上げるとプリントAとBする必要があります。そうでない場合は、あなたができることは何もありません(バーチャルにすることを超えて)。

あなたがいないのはなぜ
5

:それから、私はあなたがABで上書きしたいOtherClassのメソッドが仮想されていない場合だと思い

2

あなたの問題を解決する必要があり

class OtherClass 
{ 
    public: 
    virtual void anyMethod() 
    { 
     cout << "OtherClass"; 
    }; 
} 

をオーバーライドは暗黙的ではありません。

明示的に関数をオーバーライドする方法があると思います。

1

DeadMGsの回答はもちろん正しいです。

はポインタ ptrAとあなたの下の例のタイプ OtherClassptrBまたは AbstractClassです:あなたは OtherClass Methodeのを変更することができない場合でも、あなたはこれをしようとする場合があります(例えば、それは、サードパーティのLIBからですか)?

もしそれらがOtherClassであれば、あなたが説明した動作を期待します。私の知る限り、あなたのコードOtherClass::anyMethod()から見ることができるよう

dynamic_cast<AbstractClass*>(ptrA)->anyMethod();

+0

まったく.. OtherClassは私の署名を変更することができないサードパーティのライブラリにあります。私は、AbstractClassでvirtual anyFunctionを宣言することができなかったことに気付きました(申し訳ありませんが、私が投稿したのは私のコードの非常に単純化されたバージョンです)。今、私はその解決策を試してみましたが、問題はOtherClass anyFunctionにいくつかの異なるシグネチャがあることです.JavaClassですべてを再宣言しなければ、いくつかの競合が発生するようです。私はいくつかのテストを行い、後でより詳細な質問を投稿します。ありがとう – Heisenbug

1

を仮想し、すでに実装されていないです:あなたは、その後AbstractClassへのポインタをキャストしてみてください。 virtual

0

私は、2番目のケースの宣言が次のようだと思います: OtherClass * ptrA; AbstractClass * ptrAではなく、 最初のケースのように宣言した場合は、メソッドが仮想であるため問題はありませんが、OtherClassとして宣言すると、コンパイラはvtbleを使用せずにこのメソッドのアドレスを仮想化してバインドしません。

関連する問題