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

Using the derived class when deriving a from a class template

本文关键字:派生      更新时间:2023-10-16

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

完成后,我注意到这三个类共享了很多代码。所以我决定我想从一个基类:Value派生它们。该基类也将实现operator+,但它必须返回Year(或Month,或Day),而不是Value。所以我使用了一点从模板派生的魔法。

你瞧,它几乎起作用了。

operator<<可以编译,因为' Derived& '可以被解析。

但是operator+=试图从*this返回Derived&,这是一个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; };
};
我有一种感觉,我就要成功了。是否可以使用这种模板派生魔术并实现操作符+= ?

此外,令我惊讶的是,我的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; };
};

我做了一些错误的基础c'tor调用?还是gcc?还是有区别?

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

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;
}