2009-06-11 119 views
0

我們有一個類層次結構,看起來是這樣的:相同的功能,不同的返回類型的類層次

class base 
{ 
}; 

class derived1 : protected base 
{ 
private: 
    float m_price; 
    int m_quantity; 
    float m_value; 
public: 
// float calculateValue(); 
}; 

class derived2 : protected base 
{ 
private: 
    double m_price; 
    long m_quantity; 
    double m_value; 
public: 
// double calculateValue(); 
}; 

現在我們需要寫一個通過價格和數量相乘計算值的函數。目標是儘可能簡單地在將來添加新類。正如你可能知道的那樣,這不是直接的,因爲這些字段的數據類型對於不同的類是不同的。實際上,我們有這些功能在概念上做同樣的事情,但在編程方面它們是不同的操作。

爲了減少剪切和粘貼所需要的量,我能想到的,到目前爲止的解決方案是使用模板函數:

template <class A, B, C> 
A calculate_value(B price, C quantity) 
{ 
    A result; 
    // Some code to do the multiplication, not sure if template specialisation is needed 
    return result; 
}; 

class derived1 : protected base 
{ 
private: 
    float m_price; 
    int m_quantity; 
    float m_value; 
public: 
    float calculateValue() 
    { 
     calculate_value < float, float, int > (m_price, m_quantity); 
    } 
}; 

它的工作不錯,但是這將意味着我必須定義每個類中的每個成員函數。例如,如果我想要一個名爲getValue的函數,我將需要其他很多這些模板函數。

類定義的類成員的數據類型是已知的,所以不得不將它們放在函數定義中似乎是重複的。有沒有可能的方法來避免函數定義中的所有這些模板業務?

謝謝。

安迪

PS我已經看到了以下問題,但這個問題的問題是稍有不同: Returning different data type depending on the data (C++)

回答

0

二OO解決方案是創建一個類返回類型。然後,您可以將此返回類型轉換爲專門的返回類型。

在任何情況下,使用浮點數學的金錢會讓你陷入困境。

+0

我同意usinig浮點數學重複乘法/除法是不是一個好主意。這只是一個說明性的例子。事後看來,我可以選擇另一種手術。 – Andy 2009-06-11 15:07:05

5

雖然我不能說我有一個函數返回不同類型的多個派生類的想法,有一種方法可以做到這一點。

template 
class base<typename value_type> 
{ 
public: 
    value_type calculateValue(); 
}; 
class derived1 : protected base<float> 
{ 
private: 
    float m_price; 
    int m_quantity; 
    float m_value; 
}; 
class derived2 : protected base<double> 
{ 
private: 
    double m_price; 
    long m_quantity; 
    double m_value; 
}; 

這可以讓你改變在派生類中的VALUE_TYPE,但在基地申報所有的常用功能(像你應該做的)。這與STL中用於地圖等的方法類似。

0

會這樣嗎?

template <typename A,typename B,typename C> 
class base{ 
protected: 
    A m_price; 
    B m_quantity; 
    C m_value; 
public: 
    C calculateValue(){ 
     m_value = m_quantity * m_price; 
     return m_value; 
    } 
}; 

class derived1 : public base<int,float,int>{ 
}; 

class derived2 : public base<long,double,long>{ 
}; 
1

使用奇異遞歸模板模式(CRTP):

template <typename DERIVED> 
class base { 
protected: 
    typename DERIVED::value_type calculateValue() { 
     DERIVED *self = static_cast<DERIVED *>(this); 
     return self->m_price * self->m_quantity; 
    } 
}; 

class derived1 : protected base<derived1> { 
public: 
    typedef float value_type; 
    float m_price; 
    int m_quantity; 
}; 

class derived2 : protected base<derived2> { 
public: 
    typedef double value_type; 
    double m_price; 
    long m_quantity; 
}; 

請注意,我不得不做出m_pricem_quantity公衆,以便基類可以訪問它們。您可能不想這樣做,所以您需要添加公共訪問器(或者使用那些已存在的訪問器,如果有的話),或者使它們成爲基類的受保護成員(由typedefs指定的類型)在派生類中),或者讓派生類將基類聲明爲朋友。

如果你想公開getValue成員函數,你可以將它添加到基類並使繼承公開。

0

你可以這樣做:

 
template 
class base 
{ 
public: 
    void calculateValue(value_type& x); 
}; 
class derived1 : protected base 
{ 
private: 
    float m_price; 
    int m_quantity; 
    float m_value; 
}; 
class derived2 : protected base 
{ 
private: 
    double m_price; 
    long m_quantity; 
    double m_value; 
}; 
相關問題