2016-08-29 117 views
1

考虑我有一系列派生类例如以下所列:继承和成员函数

class A 
{ 
... 
} 

class B1 : public A //there may be many B's here say, B2, B3 etc 
{ 
... 
} 
class C1 : public B1 //may be more C's as well 
{ 
... 
} 

我想把所有在单个容器中的对象的,因此,所有的将类型类A的。

假设我想为类C1添加一个函数,那么最好的方法是什么?我的选择是在基类A中引入它,并在C1中写入所需的实现,或者,我可以在C1中引入它并进行动态转换以访问它。哪一个是首选?动态铸造是否太昂贵? (我的主要约束是运行时间。我在基类中有一个标志来指示它是什么类型的派生对象,因此我不必动态地转换容器中的每个对象。是否将不必要的函数添加到基类会导致?在恶劣的指令高速缓存使用)

+4

没有人能告诉你动态铸造是否“太贵”,因为你可以负担得起的是主观的。由于这看起来就是你所追求的(“我的主要约束就是运行时间”),我会建议这样做,并对结果进行基准测试,看看它是否对于特定的硬件和编译器优化和用例来说太昂贵,外部限制和... – Altainia

+2

使接口太广泛是糟糕的设计,因此是向下广播,您可能需要一个指向更多特定接口的额外集合。 – imreal

+0

您可以使用具有访问者模式的“变体”。 – AndyG

回答

2

你不告诉我们,新功能的目的C1,这影响答案,但粗糙的准则:

  • 如果新功能是你可能需要的任何对象的一般行为,而C1恰好是第一个用户,绝对只需将接口添加到A即可。
  • 如果新的功能是特定于C一系列类它可以遵循一些一般模式(例如后处理)中,添加一个post_process方法A,在C1覆盖它,并有方法调用C1的私有实现方法来执行实际的特定后处理任务。
  • 如果这两种情况都不是这种情况,那么您可能希望重新考虑您对继承的使用,因为您可能会使用它来表示除替换之外的其他关系。
+0

由于私有数据的类型,只能在'C1'中执行新函数它有权访问并且不被频繁调用。 – user6386155

0

添加虚拟函数的基类更好,因为:

  • 你应该避免尤其是在性能敏感的代码动态转换。请参阅Performance of dynamic_cast?

  • 在执行特定于类型的操作之前,您应该避免有条件检查对象类型(例如,是A,B1还是C1?)。不仅因为它很慢,而且因为如果你这样做,每次添加一个新的对象类型(例如C2),你都需要检查所有这些条件,看看它们是否需要更新。