2011-01-24 193 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例如,做工精細。該抽象類 方法anyMethod的具體實施將在運行時被調用。 但抽象類是由具有不虛 的方法稱爲anyMethod另一個基類派生:

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. 

現在,如果我嘗試類似的東西:

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

我是什麼誤會? 有沒有解決方案使ptrA和ptrB打印A和B而不使用cast,typeid等?

+0

請格式化您的代碼 – Elalfer 2011-01-24 17:47:44

+3

A和B也應在第二種情況下打印。你從描述中遺漏了什麼? – vitaut 2011-01-24 17:53:42

回答

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 

我做了兩個錯誤:

  1. 在我真正的代碼(而不是簡化版本之前發佈)我忘了申報虛擬 函數foo()

  2. 即使宣佈虛擬是不夠的。實際上,該函數的所有實現都必須包含在Abstract類中,以便對子類A和b可見。否則不會編譯。

我不知道它是否可以是一個乾淨的解決方案..事實上,我需要包裝所有foo方法簽名。

2

如果anyMethod在您有指針或引用的基類中聲明爲虛擬,那麼應該應該虛擬查找並正確打印A和B.如果不是,那麼你就無能爲力(除了把它變成虛擬的)。

5

你爲什麼不這樣做:

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

這應該解決您的問題

2

我認爲,如果你想在AB覆蓋在OtherClass的方法不虛,那麼,覆蓋不是隱含的。

我相信有一種方法可以明確地覆蓋這些函數,然後看看。

1

DeadMGs的答案當然是正確的。但是,如果你不能改變OtherClass了Methode(例如,從第三方的lib的),你可能想試試這個:

是指針ptrA,在低例如OtherClassptrBAbstractClass

如果他們是OtherClass我會期待你描述的行爲。你可以嘗試鑄造指針AbstractClass則:

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

1

據我可以從你的代碼OtherClass::anyMethod()看到的不是一個虛擬的和已經實施。它應該像你描述的那樣工作,如果你將其定義爲virtual

0

我認爲你的第二種情況的聲明是: OtherClass * ptrA;而不是AbstractClass * ptrA; 如果您聲明爲第一種情況,則不存在任何問題,因爲該方法是虛擬的,但如果聲明爲OtherClass,則編譯器將不會找到虛擬並且不使用vtble而綁定到此方法的地址。