从类模板派生时使用派生类

时间:2014-03-15 17:04:28

标签: c++ templates inheritance

我想为DayMonthYear编写三个基本上只包装int的包装类。我的目标是获得一些类型安全性,并且不能意外地为void date(int y, int m, int d)这样的函数切换参数。

当我完成时,我注意到这三个类共享很多代码。所以我决定从基类派生它们:Value。该基类还将实现operator+,但必须返回Year(或MonthDay),而不是Value。所以我选择了一些衍生自模板的魔法。

而Lo和Behold:它几乎可以工作。

operator<<编译,因为`Derived&amp;'可以解决。

operator+=尝试从Derived&返回*this,这是Value&

template<class Derived>
class Value {
protected:
    int value_;
public:
    explicit Value(int v) : value_{v} {}
    int value() const { return value_; }
    Derived& operator+=(const Derived& other) {
        value_ += other.value_;
        return *this;                               // ERROR!
    }
    friend ostream& operator<<(ostream& os, const Derived& x) {
        return os << x.value_;
    }
};

class Year2 : public Value<Year2> {
public:
    explicit Year2(int v) : Value<Year2>(v) {}     // NOTICE <Year2>
    bool isLeap() const { return value_ % 4 == 0; };
};

我有这种感觉,我几乎就在那里。 可以使用这种模板 - derive-magic并实现operator + =?

另外,令我惊讶的是,我的gcc-4.9.0与我如何调用基本构造函数无关。以下也有效:

class Year3 : public Value<Year3> {
public:
    explicit Year3(int v) : Value(v) {}            // NOTICE no <...>
    bool isLeap() const { return value_ % 4 == 0; };
};

我是否对基本电话做错了什么?或者它是gcc吗?或者有区别吗?

1 个答案:

答案 0 :(得分:2)

您可以使用static_cast来返回正确的指针。

return *(static_cast<Derived*>(this));

或者

return static_cast<Derived&>(*this);  

然而,似乎这可能是不必要的。您似乎并没有真正将Value类作为模板。有这个原因吗?

这还不够吗?

class Value {
protected:
    int value_;
public:
    explicit Value(int v) : value_{v} {}
    int value() const { return value_; }
    Value& operator+=(const Value& other) {
        value_ += other.value_;
        return *this;
    }
    friend ostream& operator<<(ostream& os, const Value& x) {
        return os << x.value_;
    }
};

class Year2 : public Value {
public:
    explicit Year2(int v) : Value(v) {}
    bool isLeap() const { return value_ % 4 == 0; };
};

int main()
{
    Year2 y1(1), y2(2);
    y1 += y2;
    cout << y1;
    return 0;
}