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 based on the data (C++)

4

5 回答 5

6

虽然我不能说我喜欢使用返回不同类型的函数的多个派生类的想法,但有一种方法可以做到这一点。

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 中用于地图等的方法。

于 2009-06-11T15:01:15.350 回答
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;
};

请注意,我必须 makem_pricem_quantitypublic 以便基类可以访问它们。您可能不想这样做,因此您需要添加公共访问器(或使用已经存在的访问器,如果有的话),或者使它们成为基类的受保护成员(由 typedefs 指定的类型)在派生类中),或者让派生类将基类声明为朋友。

如果你想要一个公共的getValue成员函数,你可以将它添加到基类中并公开继承。

于 2009-06-11T15:25:02.360 回答
0

OO 解决方案是创建一个返回类型的类。然后,您可以将此返回类型子类化为专门的返回类型。

无论如何,使用浮点数学来赚钱会给你带来麻烦。

于 2009-06-11T15:00:20.780 回答
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>{
};
于 2009-06-11T15:01:54.320 回答
0

你可以这样做:

模板
类基
{
上市:
    无效计算值(值类型& x);
};
类派生1:受保护的基础
{
私人的:
    浮动 m_price;
    诠释m_数量;
    浮动 m_value;
};
类派生2:受保护的基础
{
私人的:
    双倍价格;
    长 m_quantity;
    双 m_value;
};
于 2009-06-11T17:57:09.407 回答