C++虚函数覆盖
C++ virtual function override
我有一个 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’
计划通过制作更具体的实例来专门化 class,例如 point2D
、point3D
。但是,我只希望该函数使用相同 class 的类型。所以如果point2D
从哪里继承这个class,方法distTo
应该只接受point2D
类型的参数。我怎样才能做到这一点?
这是我在执行上述操作之前尝试过的方法:
virtual double distTo(point& other) = 0;
但是当我在 point2D
class 中覆盖此方法并尝试将参数替换为 point2D
类型之一时,我 运行 进入编译器错误。
感谢您的宝贵时间
我认为您的要求对于静态类型语言(例如 C++)毫无意义。
想想你将如何使用你的虚函数:
point2d p1, p2;
point3d p3;
point &p = p1;
p.distTo(p2); //ok?
p.distTo(p3); //error?
那根本不可能,因为在编译时编译器不知道 p
是对 point2d
还是 point3d
的引用,只有在运行时才知道。
如果做错了,您可以添加显式强制转换和运行时断言,但我认为这没什么意义。简单地做:
struct point { /*...*/ };
struct point2d : point {
double distTo(const point2d &other);
};
struct point3d : point {
double distTo(const point3d &other);
};
并且不要使用基础 point
引用调用 distTo
。
更新:如果你知道你的列表是同质的,但你不知道基数,那么你可以这样做:
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
,结果将是未定义的!
这听起来像是 Curiously Recurring Template Pattern。此外,这与动态间接寻址完全不兼容,因为编译器无法静态验证动态类型(显然)。但是CRTP只能用来实现功能,不能声明。
template<typename T> class Point {
public:
double distTo(T other) {
/* stuff */
}
};
class Point2D : public Point<Point2D> {
// distTo automatically defined
};
从根本上说,您尝试声明的接口是完全不可能的,因为您要求编译器对动态类型进行静态类型检查。没有提供您想要的所有属性的解决方案。
我有一个 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’
计划通过制作更具体的实例来专门化 class,例如 point2D
、point3D
。但是,我只希望该函数使用相同 class 的类型。所以如果point2D
从哪里继承这个class,方法distTo
应该只接受point2D
类型的参数。我怎样才能做到这一点?
这是我在执行上述操作之前尝试过的方法:
virtual double distTo(point& other) = 0;
但是当我在 point2D
class 中覆盖此方法并尝试将参数替换为 point2D
类型之一时,我 运行 进入编译器错误。
感谢您的宝贵时间
我认为您的要求对于静态类型语言(例如 C++)毫无意义。
想想你将如何使用你的虚函数:
point2d p1, p2;
point3d p3;
point &p = p1;
p.distTo(p2); //ok?
p.distTo(p3); //error?
那根本不可能,因为在编译时编译器不知道 p
是对 point2d
还是 point3d
的引用,只有在运行时才知道。
如果做错了,您可以添加显式强制转换和运行时断言,但我认为这没什么意义。简单地做:
struct point { /*...*/ };
struct point2d : point {
double distTo(const point2d &other);
};
struct point3d : point {
double distTo(const point3d &other);
};
并且不要使用基础 point
引用调用 distTo
。
更新:如果你知道你的列表是同质的,但你不知道基数,那么你可以这样做:
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
,结果将是未定义的!
这听起来像是 Curiously Recurring Template Pattern。此外,这与动态间接寻址完全不兼容,因为编译器无法静态验证动态类型(显然)。但是CRTP只能用来实现功能,不能声明。
template<typename T> class Point {
public:
double distTo(T other) {
/* stuff */
}
};
class Point2D : public Point<Point2D> {
// distTo automatically defined
};
从根本上说,您尝试声明的接口是完全不可能的,因为您要求编译器对动态类型进行静态类型检查。没有提供您想要的所有属性的解决方案。