假设您有以下内容:
class Shape // base class
{
private:
bool degenerate, ill_defined;
...
public:
bool isVoid () { return false; }
bool isCircle() { return false; }
bool isPoint () { return false; }
bool isPlane () { return false; }
bool isSphere() { return false; }
...
};
class Void : public Shape {
...
}
class Plane : public Shape
{
public:
bool isPlane() { return !degenerate && !ill_defined; }
bool isVoid () { return ill_defined; }
...
operator Void () throw() {
if (isVoid()) return Void();
else throw ...; //some error
}
...
}
class Point : public Shape {
private:
double radius;
...
public:
bool isPoint() { return !ill_defined; }
bool isVoid () { return ill_defined; }
...
operator Void () throw() { ... }
...
}
class Circle : public Shape // similar to the rest
class Sphere : public Shape // similar to the rest
Plane
a和 a之间的交集Sphere
可以是
- a
Circle
(如果平面“穿过”球体) - a
Point
(如果平面“刚刚接触”球体) - a
Void
(如果球体完全位于平面上方或下方)
我想知道如何最好地定义和使用 aPlane
和 a之间的交集Sphere
,因为假设的返回类型
intersect(const Sphere& S, const Plane& P)
编译时方法/自由函数是未知的。
我以前从未遇到过这种情况,所以我查找了一些可能的方法来做到这一点。我遇到了这个建议的问题boost::variant
。在我的情况下,这看起来像
boost::variant<Void, Point, Circle> intersection =
intersect(const Sphere& S, const Plane& P);
但这有三个缺点:
- 很丑
之类的东西
intersection.radius
不能按原样使用,因为Point
andVoid
没有radius
. 你必须做类似的事情if (intersection.isPoint()){ ... } else if (intersection.isCircle()) { // possibly cast to Point if degenerate, otherwise: double R = intersection.radius; ... } // etc.
实现所有这些形状的库的用户总是必须知道通过交叉两个形状可以返回哪些类型。也就是说,用户总是必须声明一些
boost::variant<scope::Void, scope::Point, scope::Circle>
复杂且丑陋的类型。幸运的是,c++11 有这个auto
关键字。或者,您可以使用这样的成员class Sphere : public Shape { ... public: boost::variant<scope::Void, scope::Point, scope::Circle> intersect_type; intersect_type intersect(const Plane& P); ... };
这样我们就可以使用
Sphere::intersect_type t = S.intersect(P);
其中
S
是 的一个实例Sphere
和P
的一个实例Plane
。但是我们仍然必须单独处理所有可能的类型:if (intersection.isPoint()){ ... } else if (intersection.isCircle()){ intersection.radius; } // etc.
所以我们试图从用户那里带走的复杂性实际上仍然存在。
我觉得我在这里遗漏了一些东西。也许有一种更聪明的方法来实现我的Shape
基类?还是我应该创建一个单独的专用Intersect
课程?对于这种情况,哪种解决方案最优雅、最有效和最有效?