2016-11-18 61 views
0

CharRow類與這些字段:如何重寫操作+在子類中

protected: 
char* ptr; 
int ROW_MAX_LENGTH; 

而且有子類BigIntegerNumber(數字的字符數組)。 我的運營商+在CharRow:

virtual CharRow operator+ (CharRow row2) 
{ 
    int row1Length = this->getRowCurrentLength(); 
    int row2Length = row2.getRowCurrentLength(); 

    CharRow tempRow(row1Length + row2Length); 

    for(int i = 0; i < row1Length; i++){ 
     tempRow.ptr[i] = this->ptr[i]; 
    } 

    for(int i = 0; i < row2Length; i++){ 
     tempRow.ptr[i + row1Length] = row2.ptr[i]; 
    } 

    return tempRow; 
} 

我需要做什麼來調用operator+多態?

BigIntegerNumber operator+ (BigIntegerNumber row2) 
{ 
    BigIntegerNumber temp(this->getRowCurrentLength() + row2.getRowCurrentLength()); 
    temp = BigIntegerNumber::addValue(*this, row2); 
    return temp; 
} 
+2

請嘗試創建一個[最小,完整和可驗證示例](http:// stackoverflow。com/help/mcve)並向我們展示,而不是脫離一些片段。並請[請閱讀如何提出好問題](http://stackoverflow.com/help/how-to-ask)。 –

+0

[虛擬賦值運算符C++]的可能重複(http://stackoverflow.com/questions/669818/virtual-assignment-operator-c) – Garf365

回答

0

虛擬operator +can work in general,但是它的工作,一些制約因素必須得到滿足。

爲什麼它不會工作你的情況的第一個原因是,該操作

BigIntegerNumber operator+ (BigIntegerNumber row2) 

不是覆蓋的

virtual CharRow operator+ (CharRow row2) 

但其超載(隱藏原來的操作員而不是覆蓋它)。

因爲它是重寫,函數簽名必須是相同的。即相同類型的參數(CharRow而不是BigIntegerNumber,最好通過const ref傳遞比值),以及相同或協變的返回類型。這些都不符合。

這樣的事情有時是通過使用一個「常規」的虛函數來完成的,這個函數將接口引用作爲參數,並通過調用這樣的func來實現非虛函數。

在這種情況下,主要問題是返回參數,因爲您無法將返回類型定義爲按值CharRow並實際返回BigIntegerNumber(它將被切片爲返回類型)。您可能更喜歡operator +=,它可以將參考返回給自己,從而能夠多形地工作。


operator +=的例子(其不具有與返回值的類型的問題):

#include <iostream> 
using namespace std; 

struct Base 
{ 
    virtual Base& operator +=(const Base& other); // takes Derived as well for the virtual calls 
}; 


struct Derived: Base 
{ 
    Derived& operator +=(const Base& other); // override - called via virtual 
    Derived& operator +=(const Derived& other); // overload - not called via virtual 
               // remove to always call the polymorphic version 
}; 

Base& Base::operator +=(const Base& other) 
{ 
    cout << "Base::operator +=(Base)"; 
    // beware this is slow! 
    const Derived* d = dynamic_cast<const Derived*>(&other); 
    if (d) 
     cout << " - called with Derived"; 
    else 
     cout << " - called with Base"; 
    cout << endl; 
    return *this; 
} 

Derived& Derived::operator +=(const Base& other) 
{ 
    cout << "Derived::operator +=(Base)"; 
    // beware this is slow! 
    const Derived* d = dynamic_cast<const Derived*>(&other); 
    if (d) 
     cout << " - called with Derived"; 
    else 
     cout << " - called with Base"; 
    cout << endl; 
    return *this; 
} 

Derived& Derived::operator +=(const Derived& other) 
{ 
    cout << "Derived::operator +=(Derived)" << endl; 
    return *this; 
} 

int main() 
{ 
    Derived d1, d2; 
    Base b, b0; 
    Base& b1 = d1; 
    Base& b2 = d2; 

    d1 += d2; // Derived::operator +=(Derived) 
    b1 += d2; // Derived::operator +=(Base) - called with Derived 
    d1 += b1; // Derived::operator +=(Base) - called with Derived 
    b1 += b2; // Derived::operator +=(Base) - called with Derived 
    b += d2; // Base::operator +=(Base) - called with Derived 
    d1 += b; // Derived::operator +=(Base) - called with Base 
    b += b0; // Base::operator +=(Base) - called with Base 
    b1 += b; // Derived::operator +=(Base) - called with Base 

    return 0; 
} 

對於operator +值傳遞結果類型的問題。但是,在C++中仍然不是不可能的,但是你需要使用某種包裝。這種包裝的一個例子:

#include <iostream> 
#include <memory> 
using namespace std; 


struct Base; 
struct Derived; 

class BaseWrapper 
{ 
    shared_ptr<Base> _obj; 
public: 
    explicit BaseWrapper(const shared_ptr<Base>& obj) : _obj(obj) 
    {} 
    template<class RESULT_T> 
    operator RESULT_T() 
    { 
     // throws if type not correct 
     return dynamic_cast<RESULT_T&>(*_obj); 
    } 
    Base& operator +=(const Base& other); 
    BaseWrapper operator +(const Base& other) const; 
}; 

struct Base 
{ 
    virtual Base& operator +=(const Base& other); // takes Derived as well for the virtual calls 
    BaseWrapper operator +(const Base& other) const; 
private: 
    virtual shared_ptr<Base> copy() const 
    { 
     return make_shared<Base>(*this); 
    } 
}; 


struct Derived : Base 
{ 
    Derived& operator +=(const Base& other); // override - called via virtual 
private: 
    virtual shared_ptr<Base> copy() const 
    { 
     return make_shared<Derived>(*this); 
    } 
}; 

Base& BaseWrapper::operator += (const Base& other) 
{ 
    return *_obj += other; 
} 

BaseWrapper BaseWrapper::operator +(const Base& other) const 
{ 
    return *_obj + other; 
} 

BaseWrapper Base::operator +(const Base& other) const 
{ 
    BaseWrapper result(copy()); 
    result += other; 
    return result; 
} 

int main() 
{ 
    Derived d1, d2; 
    Base b, b0; 
    Base& b1 = d1; 
    Base& b2 = d2; 

    b = b1 + b2; // add Derived + Derived, result is Derived (typed Base) 
    b = b0 + d1; // add Base + Derived, result is Base 

    // d1 = b0 + d1; // add Base + Derived, result is Base, throws bad_cast (cannot cast to Derived) 

    d1 = b1 + b2; // add Derived + Derived, result is Derived 

    return 0; 
} 

即,BaseWrapper可用於通過價值轉換返回多態型,並且具有與原始類型。但是請注意,在這種情況下涉及內存分配。

+0

無法以某種方式將BigIntegerNumber轉換爲CharRow以覆蓋運算符+? – ReturnedVoid

+0

不是直接的,但請注意,如果您通過const引用傳遞,則'const Base&'版本也會獲取'Derived'的實例 - 請參閱更新。 – axalis

+0

還添加了一個示例,如何通過對結果使用包裝類型來實現多態「運算符+」。 – axalis

-1

如果你想調用CharRow ::運算符+()內BigIntegerNumber ::運算符+(),你可以做到這一點是:

BigIntegerNumber operator+(BigIntegerNumber row2) 
{ 
    return CharRow::operator+(row2); 
} 
+0

返回對臨時對象的引用(作爲運算符實現)是一個很大的否-沒有! – axalis

+0

對,我錯過了創建臨時對象的那一行。我的錯誤 – LynnXe

+0

您正在返回一個CharRow,但函數返回類型爲BigIntegerNumber - 只有當BigIntegerNumber具有來自CharRow的隱式構造函數時,這才起作用。 – Walter