2014-11-21 61 views
1

我對遺傳和多態性的概念感到困惑。我的意思是,代碼重用性和函數重寫有什麼區別?使用繼承概念重用父類函數是不可能的,否則使用Polymorphism重寫父類變量是不可能的。對我來說似乎沒有什麼區別。多態性和遺傳之間有什麼區別

class A 
{ 
    public: 
     int a; 
     virtual void get() 
     { 
     cout<<"welcome"; 
     } 
}; 

class B:public A 
{ 
    a =a+1; //why it is called code reuse 
    void get() //why it is called overriding 
{ 
    cout<<"hi"; 
} 
}; 

我的疑問是關於代碼重用和函數重寫之間的區別。

+1

你可以有繼承無多態性,但你不能真正擁有多態性沒有繼承。 – 2014-11-21 07:31:43

+0

您提到多態但不顯示使用它的代碼。 – ChiefTwoPencils 2014-11-21 07:31:56

+0

如果你不小心,這些概念可以感受到整個大學課程,並蔓延到畢業後水平。試着問一個更具體的問題。 – 2014-11-21 08:32:09

回答

2

讓我們從你的例子開始。繼承:在此,您從類A派生類B,這意味着您可以訪問其所有公共變量和方法。

a = a + 1 

在這裏,您正在使用的class A變量a,正在重用在class B變量a從而實現代碼重用。

與程序是如何調用取決於它必須完成的事情的方法多態性的交易:在您的示例您正在使用的class B方法get()覆蓋的class A方法get()。所以,當你創建B類和呼叫方法得到的實例,你會在控制檯中看到'hi''welcome'

2

功能繼承允許行爲的抽象從一個「更具體的」派生類(ES)的「更抽象「的基類。 (這與將基本數學和代數分解相類似。)在這種情況下,更抽象的簡單意味着指定較少的細節。預計派生類將擴展爲(或添加到)基類中指定的內容。例如:

class CommonBase 
{ 
    public: 
     int getCommonProperty(void) const { return m_commonProperty; } 
     void setCommonProperty(int value) { m_commonProperty = value; } 
    private: 
     int m_commonProperty; 
}; 

class Subtype1 : public CommonBase 
{ 
    // Add more specific stuff in addition to inherited stuff here... 
    public: 
     char getProperty(void) const { return m_specificProperty1; } 
    private: 
     char m_specificProperty1; 
}; 

class Subtype2 : public CommonBase 
{ 
    // Add more specific stuff in addition to inherited stuff here... 
    public: 
     float getProperty(void) const { return m_specificProperty2; } 
    private: 
     float m_specificProperty2; 
}; 

注意,在上面的例子中,getCommonProperty()setCommonProperty(int)CommonBase類繼承,並且可以在Subtype1類型和Subtype2的對象的實例來使用。所以我們在這裏繼承,,但我們並沒有真正的多態性,但是(如下面將要解釋的)。

您可能想也可能不想實例化基類的對象,但仍可以使用它來收集/指定所有派生類將繼承的行爲(方法)和屬性(字段)。因此,就代碼重用而言,如果您有多個類型的共享某些常見行爲的派生類,則可以在基類中僅指定一次該行爲,然後在所有派生類中「重複使用」,而不必複製它。例如,在上面的代碼中,getCommmonProperty()setCommonProperty(int)的規範可以說是由每個類重新使用,因爲這些方法不需要爲每個方法重寫。

多態性是相關的,但它意味着更多。它基本上意味着你可以用相同的方式處理碰巧來自不同類的對象,因爲它們都是從(擴展)公共基類派生的。爲了這個真的很有用,該語言應該支持虛擬繼承。這意味着函數簽名在多個派生類中可以是相同的(即簽名是公共抽象基類的一部分),但根據特定類型的對象會做不同的事情。

因此修改上面的例子添加到CommonBase(但保持Subtype1Subtype2同前):

class CommonBase 
{ 
    public: 
     int getCommonProperty(void) const { return m_commonProperty; } 
     void setCommonProperty(int value) { m_commonProperty = value; } 
     virtual void doSomething(void) = 0; 
     virtual ~CommonBase() { } 
    private: 
     int m_commonProperty; 
}; 

注意doSomething()在此聲明爲純虛函數在CommonBase(這意味着你不能直接實例化一個CommonBase對象 - 它不一定是這種方式,我只是這樣做以保持簡單)。但是現在,如果您有一個指向CommonBase對象的指針,它可以是或者 a Subtype1 a Subtype2,您可以在其上調用doSomething()。這將根據對象的類型做一些不同的。這是多態性。

void foo(void) 
{ 
    CommonBase * pCB = new Subtype1; 
    pCB->doSomething(); 
    pCB = new Subtype2; 
    pCB->doSomething();  // Does something different... 
} 

在你的問題中提供的代碼示例,原因get()方面被稱爲「壓倒一切」,是因爲在B::get()型式的方法中指定的行爲優先於(「覆蓋」)如果您在B對象的實例上調用get()(即使您通過A*執行操作,因爲該方法在類A中聲明爲virtual),該方法的A::get()版本中指定的行爲。

最後,關於「代碼重用」的其他評論/問題並不像您指定的那樣工作(因爲它不在方法中),但我希望如果您參考我上面寫的內容。當你從一個公共基類繼承行爲,並且你只需要爲這個行爲編寫代碼(在基類中),然後所有的派生類都可以使用它,那麼這可以被認爲是一種「代碼重用」。

+0

雖然我試圖在這裏回答這個問題,但我相信在這裏有幾個*其他答案可以解決您的問題。請查看其中一些以瞭解更多詳情。 – Turix 2014-11-21 08:27:19

相關問題