我正在尝试创建一个形状库。有以下类Shape,带有此声明:
#include "pos.h"
#ifndef SHAPE_H
#define SHAPE_H
class Shape{
protected:
Pos pos;
public:
Pos getPos();
void setPos(Pos pos);
virtual bool intersection(Shape&);
Shape():pos((Pos){0,0}){}
Shape(Pos pos):pos(pos){}
Shape(int x, int y):pos((Pos){x,y}){}
};
#endif /* SHAPE_H */
如您所见,有一个虚函数成员(交集)。此函数用于计算两个形状是否相交(如果它们是圆形,矩形或其他形状,则无任何形状)。 我还声明了这些类(圆形和矩形):
#include "pos.h"
#include "shape.h"
#ifndef RECTANGLE_H
class Rectangle;
#endif /* RECTANGLE_H */
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle : public Shape{
private:
int radius;
public:
int getRadius(){return radius;}
void setRadius(int radius){this->radius=radius;}
bool containsPos(Pos p);
bool intersection(Circle& c);
bool intersection(Rectangle& r);
Circle();
Circle(Pos pos);
Circle(int radius);
Circle(Pos pos, int radius);
};
#endif /* CIRCLE_H */
#include "pos.h"
#include "shape.h"
#ifndef CIRCLE_H
class Circle;
#endif /* CIRCLE_H */
#ifndef RECTANGLE_H
#define RECTANGLE_H
class Rectangle : public Shape{
private:
int width;
int height;
public:
int getWidth(){return width;}
int getHeight(){return height;}
void setWidth(int width){this->width=width;}
void setHeight(int height){this->height=height;}
bool containsPos(Pos pos);
bool intersection(Rectangle& r);
bool intersection(Circle& c);
Rectangle():Shape(),width(0),height(0){}
Rectangle(int w, int h):Shape(),width(w),height(h){}
Rectangle(Pos p, int w, int h):Shape(p), width(w),height(h){}
Rectangle(int x, int y, int w, int h):Shape(x,y), width(w), height(h){}
};
#endif /* RECTANGLE_H */
如您所见,我在Shape的每个子类中为Shape的每个子类创建了一个成员函数
看起来不错但有问题。当你调用一个给出一个Shape的交集时(我的意思是编译器不知道它的形状,例如从Shapes矢量中获取)作为参数时它不起作用(g ++:没有匹配的调用函数)。
我想这是因为我没有覆盖Shape的虚函数,因为只要参数不同,功能就不同了(我想)。
好吧,我想知道是否有一种很酷的方式来实现这一目标。
答案 0 :(得分:2)
设计错了。 First Shape需要一个名为BoundingRect
的虚方法,它返回派生类填充区域的Top,Left,Bottom,Right。然后Shape.intersection做的第一件事是确定边界矩形是否相交;一项微不足道的练习。
现在变得更难了。每个形状必须提供一个虚拟名称Paths
,它返回一个列表/数组的线段/贝塞尔曲线,真正描述该区域。然后intersection
方法确定任一形状中的任何路径是否相交。
答案 1 :(得分:1)
启用run time type information,创建一个实际采用Shape类的交集方法,并使用dynamic_cast找出你得到的对象,然后调用派生对象上的重载交集调用。
请注意,RTTI会严重降低代码速度,并且对每种形状都有特殊功能会严重影响代码的灵活性和可维护性。像理查德提出的一般化解决方案从长远来看可能更有利。