c – 面向对象:如何从多个实现中进行选择

我是一个不错的程序程序员,但我是面向对象的新手(我曾经在好老帕斯卡和C上接受过工程师培训).我发现特别棘手的是选择多种方法中的一种来实现同样的目的.对于C来说尤其如此,因为它的功能可以让你做任何你喜欢的事情,甚至可怕的事情(我想这里的权力/责任格言是合适的).

我认为这可能有助于我运行一个我正在与社区斗争的特定案例,以了解人们如何做出这些选择.我正在寻找的是与我的具体情况相关的建议,以及更一般的指针(没有双关语意).开始:

作为练习,我正在开发一个简单的模拟器,其中“几何表示”可以有两种类型:“圆”或“多边形”.然后,模拟器的其他部分将需要接受这些表示,并可能以不同方式处理它们.我已经提出了至少四种不同的方法来做到这一点.每个的优点/缺点/权衡取舍是什么?

答:功能重载

将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()).

解决方法

以下是我教我的OO学生的一些设计规则(拇指):

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的答案,你需要一个基类/接口类和派生圆和多边形的子类.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...