2011-09-28 87 views
1

我有下面的類表示數值陣列繼承和操作符重載

class Array { 

protected : 
    double *data; // this will hold the data of the array 
    int  n;  // number of elements in the array 

public : 
    virtual Array operator+ (double value) const { 
     // return a new array with the argument added to each element 
    } 

    // other declarations follow here... 
}; 

和另一類與前一個繼承和添加的布爾掩碼的每個元素

class MaskedArray : public Array { 

private : 
    bool *mask; // this holds the boolean mask of the array 

public : 
    MaskedArray operator+ (double value) const { 
     // return a new MaskedArray with the argument added to each element 
    } 

    // other declarations follow here... 
} 
「無效協變返回類型」的錯誤

當我嘗試編譯時,我得到錯誤「invalid covariant return type」,這是正常的,因爲兩個類中的兩個重載運算符具有相同的簽名。

我能夠通過引用繼承類的重載操作符的參數而不是通過值來繞過這個問題,因爲這改變了函數的簽名,同時保持兩個類的接口。但我覺得這不是很乾淨,如果我想從MaskedArray繼承,該怎麼辦?我會面臨同樣的問題。

我希望能夠寫出這樣的東西在我的客戶端代碼

Array array; 
// populate array here 
Array array2 = array + 1.0; 

MaskedArray maskedArray; 
// populate maskedArray here 
MaskedArray maskedArray2 = maskedArray + 1.0 

有另一種更優雅的方式比我的「黑客」來實現這一目標?

+0

如果基類函數是虛擬的,那麼只應該得到關於「無效協變返回類型」的錯誤。你確定這是給你錯誤的_exact_代碼嗎? –

+0

順便說一句,繼承真的是'Array'和'MaskedArray'的正確關係嗎? 'Array'的掩蔽附加函數會更好嗎?從概念上講,一個'MaskedArray'不能替代'Array',並且實際上這兩個工作都是一個好主意?數組x = static_cast (maskedArray)+ 5.0;'和'Array y = maskedArray + 5.0;' –

回答

0

用於您的問題的解決方法可以使用,而不是遏制繼承:

class MaskedArray { 

private : 
    Array array; 
    bool *mask; // this holds the boolean mask of the array 

public : 
    MaskedArray operator+ (double value) const { 
     // return a new MaskedArray with the argument added to each element 
    } 

    // delegate public functions 
} 

Ofcourse,現在MaskedArray不能使用陣列的保護成員(在很多情況下,這是一件好事)並且公共接口必須被委託。

1

首先,您報告的關於協變結果的錯誤是與提供的代碼不一致。

它只出現在虛擬成員函數中,在我提到的代碼中,沒有這樣的代碼。

不要在將來通過詢問有什麼錯你真正的代碼,並提出一些由幻想代碼再浪費時間了。

無論如何,治癒:在你的真實代碼,只是刪除單詞virtual

此外,建議的話:使用std::vector來保存數據並負責分配,複製和釋放。

+1

PS:如果你絕對必須使用繼承,爲什麼不使用'private'? –

+0

ooops,對不起,我浪費了你的時間;)實際的代碼當然比我提出的要多,我只是試圖爲我的特定問題提取相關部分。感謝您的建議。 – kokozul

+0

@kokozul簡化問題的代碼實際上是很好的,但這樣做時,您必須確保您不會過分簡化*,直到它沒有意義。一個合理的方法將試圖提供一個最小的例子,其中錯誤被重現,在這種情況下需要'virtual'關鍵字。一旦你有這個最小的例子以預期的方式失敗,就用它作爲答案的來源。 –

0

協變表示重寫的虛函數的返回類型是從基類函數的返回類型繼承的。

但是:儘管協方差通常由C++支持,但該標準僅在返回指針或引用時才允許協方差。 operator+按值返回,這就是爲什麼你得到編譯器錯誤。這不是特定於運營商,而是適用於每個功能。

刪除virtual關鍵字將消除編譯器錯誤。但是,如果你這樣做,請記住,應用operator+Array引用或指針,這實際上引用MaskedArray返回一個Array(因此不包含mask成員。如果你把它轉換爲MaskedArray原來mask丟失) 。