2014-04-17 73 views
1

這是我的代碼:多態性與抽象類(C++)

#include <cstdlib> 
#include <vector> 
#include <iostream> 
#include <cstring> 

using namespace std; 
//abstract class 
class GMatrix { 
    string name; 
    int nrows; 
    int ncols; 
public: 
    GMatrix(const string & n, int nr, int nc); 
    virtual GMatrix& add(const GMatrix&)= 0; 
}; 

class RMatrix : public GMatrix { 
    vector<int>numbers; 
public: 
    RMatrix(const string & n, int nr, int nc, vector<int> nums); 
    RMatrix& add(const RMatrix&); 
}; 

GMatrix::GMatrix(const string& n, int nr, int nc){ 
    name=n; 
    nrows=nr; 
    ncols=nc; 
} 

RMatrix::RMatrix(const string & n,int nr, int nc, vector<int> nums):GMatrix(n,nr,nc){ 
    numbers=numbers; 
} 

RMatrix& RMatrix::add(const RMatrix& x){ 
    for(int i =0; i = numbers.size(); i++){ 
     numbers.at(i)+=x.numbers.at(i); 
    } 
} 

int main(int argc, char** argv) { 
    vector<int> n; 
    for (int i = 0; i < 16 ; i++){ 
     n.push_back(i); 
    } 

    RMatrix a("a",4,4,n); 
    return 0; 
} 

正如你看到的,我的程序包括兩個類,一個(父類)的是在這裏抽象這樣的方法沒有的功能和一個孩子類。我的問題是,這個代碼無法建立。我嘗試創建一個對象作爲RMatrix對象,但編譯器顯示這樣的錯誤,我不明白:

main.cpp:48:13: error: cannot declare variable ‘a’ to be of abstract type ‘RMatrix’ 
main.cpp:18:7: note: because the following virtual functions are pure within ‘RMatrix’: 
main.cpp:15:23: note: virtual GMatrix& GMatrix::add(const GMatrix&) 

回答

4

問題是RMatrixadd成員函數與GMatrix中的純虛函數add函數的簽名不匹配。

你需要的是

GMatrix & RMatrix::add(const GMatrix &) 

,但你有什麼是

RMatrix & RMatrix::add(const RMatrix &) 

你有沒有簽名概念相匹配的功能(如,本款對一般OOP,不只是C++),因爲儘管所有的RMatrix都是GMatrixs,但並不是所有的GMatrix都是RMatrixs。這意味着如果有人做類似的創建類GMatrix,然後創建FooMatrixRMatrix的實例並使用GMatrix引用來訪問它們,他們將不能使用RMatrix& RMatrix::add(const RMatrix&)方法添加這兩個矩陣,即使GMatrix指定具體子類實現的add方法必須能夠使用任何GMatrix來調用。

+0

這不能解決問題,因爲常量GMatrix沒有成員數量 – 4pie0

+0

@ privatedatapublicchannel2它不會立即導致工作代碼,但我相信它給提問者足夠的信息來修復他們的代碼並在將來避免該問題。 –

+0

@Eric:除了代碼無法修復外,還有一個核心設計問題,因爲繼承關係不遵循LSP –

1

RMatrix也是一個抽象類,因爲你還沒有實現的

virtual GMatrix& add(const GMatrix&)= 0; 

方法。在RMatrix中,此方法仍然是純虛擬的。這就是爲什麼你不能構造一個對象。

3

你打破了Liskov的替代原則。您的派生類型不能用於代替基數,因爲您可以將添加到任何GMatrix到基數,但只有RMatrix到派生類型。

在派生類型的add成員函數是不被所述基類型相同的名稱的成員函數的覆蓋

1

方法

RMatrix& RMatrix::add(const RMatrix&); 

不會覆蓋

virtual GMatrix& GMatrix::add(const GMatrix&)= 0; 

因爲GMatrix::add是純虛所以代碼失敗。您可以添加{}來解決問題(順便說一下,看起來您根本不需要GMatrix::add ...):

class GMatrix { 
    string name; 
    int nrows; 
    int ncols; 
public: 
    GMatrix(const string & n, int nr, int nc); 
    virtual GMatrix& add(const GMatrix&){} 
}; 

class RMatrix : public GMatrix { 
    vector<int>numbers; 
public: 
    RMatrix(const string & n, int nr, int nc, vector<int> nums); 
    RMatrix& add(const RMatrix&); 
}; 

http://ideone.com/SLObkC

+0

不好。純虛擬函數用於強制開發人員覆蓋它們。如果你刪除純虛函數,當你有這樣的事情: 'GMatrix * matrix = new RMatrix;矩陣 - >添加(其他);'它不會做任何事情。 –