我认为这可能有助于我运行一个我正在与社区斗争的特定案例,以了解人们如何做出这些选择.我正在寻找的是与我的具体情况相关的建议,以及更一般的指针(没有双关语意).开始:
作为练习,我正在开发一个简单的模拟器,其中“几何表示”可以有两种类型:“圆”或“多边形”.然后,模拟器的其他部分将需要接受这些表示,并可能以不同方式处理它们.我已经提出了至少四种不同的方法来做到这一点.每个的优点/缺点/权衡取舍是什么?
答:功能重载
将Circle和Polygon声明为不相关的类,然后重载需要几何表示的每个外部方法.
B:铸造
声明一个枚举GeometricRepresentationType {Circle,Polygon}.声明一个抽象的GeometricRepresentation类,并从中继承Circle和Polygon. GeometricRepresentation有一个虚拟的Gettype()方法,由Circle和Polygon实现.然后,方法使用GetType()和switch语句将GeometricRepresentation转换为适当的类型.
C:不确定合适的名字
像在B中一样声明一个枚举类型和一个抽象类.在这个类中,还创建函数Circle * ToCircle(){return NULL;}和Polygon * ToPolygon(){return NULL;}.每个派生类然后重载相应的函数,返回此.这仅仅是动态铸造的重新发明吗?
D:一起束缚他们
将它们实现为具有枚举成员的单个类,该成员指示对象的类型.该类具有可以存储两种表示的成员.然后由外部方法决定不调用傻函数(例如,多边形上的GetRadius()或圆上的GetOrder()).
解决方法
1)每当你想要创建一个枚举以跟踪对象/类中的某些模式时,你可以(可能更好)为每个枚举值创建一个派生类.
2)任何时候你写一个关于一个对象的if语句(或者它当前的状态/模式/无论什么),你可以(可能更好)进行一个虚函数调用来执行一些(更抽象的)操作,其中原始的那个 – 或者else-sub-statement是派生对象的虚函数的主体.
例如,而不是这样做:
if (obj->type() == CIRCLE) { // do something circle-ish double circum = M_PI * 2 * obj->getRadius(); cout << circum; } else if (obj->type() == POLY) { // do something polygon-ish double perim = 0; for (int i=0; i<obj->segments(); i++) perm += obj->getSegLength(i); cout << perim; }
做这个:
cout << obj->getPerimeter(); ... double Circle::getPerimeter() { return M_PI * 2 * obj->getRadius(); } double Poly::getPerimeter() { double perim = 0; for (int i=0; i<segments(); i++) perm += getSegLength(i); return perim; }
在上面的例子中,非常明显的是“更抽象”的想法是什么,外围.情况并非总是如此.有时它甚至没有一个好名字,这是很难“看到”的原因之一.但是,您可以将任何if语句转换为虚函数调用,其中“if”部分被函数的虚拟替换.
在你的情况下,我绝对同意Avi的答案,你需要一个基类/接口类和派生圆和多边形的子类.