2015-05-01 133 views
0

我想知道以下两个类设计选择中的一个在性能和/或可维护性方面是否优越,或者其他问题会优于其他问题。C++类继承设计选择

第一种方法:

基类(父)具有私有数据成员和一个纯虚拟无效的功能。子类(childA)将参数从其默认构造函数传递给父类,并使用父类的getter方法打印出其他值。

第二种方法:

基类(ONCLE)只由一个virual析构函数和纯虚方法。子类(侄子)拥有商店作为私人数据成员的价值,并具有自己的getter函数来执行某些计算。

下面是一些代码:

#include <iostream> 

class parent{ 
public: 
    parent(int x){ _x = x; } 
    virtual ~parent(){} 
    virtual void calc(void) = 0; 
    int getX(void) { return _x; } 
private: 
    int _x; 
}; 

class childA: public parent{ 
public: 
    childA(int x): parent(x){} 
    void calc(void){std::cout << "x sq: " << parent::getX()*parent::getX() << std::endl;} 
}; 


class oncle{ 
public: 
    virtual ~oncle(){} 
    virtual void calc(void) = 0; 
}; 

class nephewA: public oncle{ 
public: 
    nephewA(int x): _x(x){} 
    void calc(void){std::cout << "x sq: " << getX()*getX() << std::endl;} 
    int getX(void){ return _x; } 
private: 
    int _x; 
}; 

int main(int argc, char *argv[]) 
{ 

    parent *first = new childA(3); 
    parent *second = new childB(3); 

    first->calc(); 
    second->calc(); 

    oncle *foo = new nephewA(3); 
    oncle *bar = new nephewB(3); 
    foo->calc(); 
    bar->calc(); 


    delete bar; 
    delete foo; 
    delete second; 
    delete first; 

    return 0; 
} 

总之:第一种方法就是将重点放在家长和第二子类中。

那么是否有任何可量化的方面可以帮助我选择两种方法之一?

+3

应用程序应该确定需要什么方法。 – NathanOliver

+2

可能转移到[email protected] –

+0

这个问题只是一场辩论。不应该在这一部分。 – Khaldor

回答

1

性能:

一般来说,性能问题,在很大程度上取决于编译器的优化,应该由最好的一个特设的基准来解决。

然而,对于这个简单的例子,很明显,这两种方法的性能应该是相同的:

  • 方法1:calc()每个呼叫是虚拟呼叫(间接函数调用)。该函数调用两次父代的getX(),这是一个非虚函数调用(即每个calc()在编译时知道它必须调用哪个函数)在编译时完全确定。
  • 方法2:calc()的每次调用也是一个虚拟调用(间接函数调用)。该函数调用对象的getX()两次,这是一个非虚函数调用,在编译时完全确定。

另外,编译器可以非常容易地在这里内联非虚函数。所以优化过的代码肯定不会调用这个函数,而是直接使用这个变量。

可维护性

你应该问自己多少成员(X /的getX())真的绑定到其所定义的类,怎么可能是你的设计的每一个元素可以发展。

  • 方法1假设x是管理所有的孩子们以同样的方式,没有例外。
    • 如果是这种情况,这种设计具有集中维护的优点。例如,如果明天你需要x变成双倍,那么实施这样的演变将会很顺利。
    • 如果这个基本假设会改变,你所要做的就是为子女定义getX(),它应该有不同的行为。唯一的缺点是,这些孩子仍然会有一个私人的x,这将保持不被使用。如果你有几个对象,这不是一个严重的问题。如果你在内存中拥有数百万个这样的对象,这可能不是最理想的。
  • 方法2假设每一个侄子负责管理自己的getX()这是一个非常灵活的设计,尤其是如果有很多不同的规则:
    • 内存管理总是会针对每个侄子。如果一个侄子会例如从另一个值导出x,则不需要存储冗余信息。
    • 灵活性也可以有其缺点,特别是如果它不符合现实:它可能需要复制和粘贴许多侄子相同成员的相同定义。这样的代码将很难维护(因为任何chagne to x或getX()都必须在所有侄子之间被复制)。

结论:

正如你看到的,没有一个统一的最佳答案。这一切都取决于班级和成员之间的真正关系。

一些例子:

  • 如果父母是雇员,孩子及其在工作流程中的作用,x是年龄,我会去的方法1(x是一个真正与母体)。
  • 如果oncle是一个抽象的几何形状,newphew的具体形状如方形/三角形/ octogon,并且x是最大宽度,我会为方法2(x确实绑定到侄子)。
+0

谢谢你的详细答案。 – Vincent