我想知道以下两种类设计选择中的一种在性能和/或可维护性方面是否优越,或者是否有利于一种方法优于另一种方法。
第一种方法:
基类(父)具有私有数据成员和一个纯虚拟void函数。子类(childA)将参数从其默认构造函数传递给父级,并使用父级的getter方法打印出一些其他值。
第二种方法:
基类(oncle)只包含一个虚拟析构函数和一个纯虚方法。子类(nephew)将值存储为私有数据成员,并具有自己的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;
}
简而言之:第一种方法强调父类,第二种方法强调子类。
那么有任何可量化的方面可以帮助我选择两种方法中的一种吗?
答案 0 :(得分:1)
<强>性能:强>
通常,性能问题在很大程度上取决于编译器的优化器,最好通过ad-hoc基准来解决。
尽管如此,对于这个简单的例子,两种方法的表现应该是相同的:
calc()
都是虚拟调用(间接函数调用)。该函数调用两次父的getX(),这是一个非虚函数调用(即每个calc()在编译时知道它必须调用哪个函数)在编译时完全确定。 calc()
的每次调用也是虚拟调用(间接函数调用)。该函数调用两次对象的getX(),这是一个非虚函数调用,在编译时完全确定。 此外,编译器可以非常容易地在此处内联非虚函数。因此,优化的代码肯定不会调用函数,而是直接使用变量。
<强>可维护性强>
你应该问问自己成员(x / getX())实际上与定义它们的类绑定了多少,以及你的设计的每个元素可能发展的可能性有多大。
getX()
。唯一的缺点是这些孩子仍然会有一个私人的x,它将保持未使用状态。如果你有几个对象,这不是一个严重的问题。如果你在内存中有数百万个这样的对象,这可能不是最理想的。 getX()
这是一个非常灵活的设计,特别是如果有许多不同的规则:
结论:
如你所见,没有一个最好的答案。这完全取决于类和成员之间的真实关系。
一些例子: