C ++虚函数覆盖

时间:2015-04-11 18:15:51

标签: c++ inheritance polymorphism abstract-class

我有一个包含以下虚拟方法的类:

struct point {
    template<typename T>
    virtual typename std::enable_if<std::is_base_of<point, T>::value, double>::type distTo(T &other) const = 0;
};

上述方法无效,因为:

error: templates may not be ‘virtual’

计划是通过制作类似point2Dpoint3D的更具体的实例来专门化该类。但是,我只希望该函数与同一类的类型一起使用。因此,如果point2D继承此类,则方法distTo应仅采用类型point2D的参数。我怎么能做到这一点?

这是我在做上述事情之前尝试过的事情:

virtual double distTo(point& other) = 0;

但是当我在point2D类中重写此方法并尝试用point2D类型的参数替换该参数时,我遇到了编译器错误。

感谢您的时间

2 个答案:

答案 0 :(得分:3)

这听起来像奇怪的重复模板模式。此外,这与动态间接完全不兼容,因为编译器无法静态验证动态类型(显然)。但是CRTP只能用于实现函数,而不是声明它。

template<typename T> class Point {
public:
    double distTo(T other) {
        /* stuff */ 
    }
};
class Point2D : public Point<Point2D> {
    // distTo automatically defined
};

从根本上说,您尝试声明的接口完全不可能,因为您要求编译器静态地检查动态类型。没有解决方案可以提供您想要的所有属性。

答案 1 :(得分:1)

我认为你的要求对于C ++这样的静态类型语言毫无意义。

考虑一下如何使用虚拟功能:

point2d p1, p2;
point3d p3;

point &p = p1;

p.distTo(p2); //ok?
p.distTo(p3); //error?

这根本不可能,因为在编译时编译器不会知道p是否是对point2dpoint3d的引用,仅在运行时。

如果你做错了,你可以添加一个显式的强制转换和运行时断言,但我认为它没有多大意义。只需:

struct point { /*...*/ };

struct point2d : point {
    double distTo(const point2d &other);
};

struct point3d : point {
    double distTo(const point3d &other);
};

请勿使用基本distTo引用来致电point

更新:如果你知道你的列表是同质的,但你不知道基数,那么你可以这样做:

struct point {  
    virtual double distTo(const point &other) =0;
};

struct point2d : point {
    double distTo(const point2d &other) { /*...*/ }
    virtual double distTo(const point &other) {
        const point2d &other2 = static_cast<const point2d &>(other);
        return distTo(other2);
    }
};

struct point3d : point {
    double distTo(const point3d &other) { /*...*/ }
    virtual double distTo(const point &other) {
        const point3d &other3 = static_cast<const point3d &>(other);
        return distTo(other3);
    }
};

但要注意!如果使用错误的对象调用point::distTo,结果将是未定义的!