C++,继承 vs 多态性

4

我有一个略带哲学意味的问题。有一个类A

class A
{

}

并且类A1、A2、A3都是从A继承而来的。

class A1 : public A
{
}

class A2 : public A
{
}

class A3 : public A
{
}

有一个处理对象A-A3的静态方法,应该优先选择哪个变量?

A)
class Algorithms  
{
  //Object of derived class could be use instead of the object base class
  public: void test (const A *a) {}
};

或者
B)
class Algorithms
{
  public: 
  //Templatize parameter
  template <typename TType>
  void (const TType *a) {}
};

在我看来,在这种情况下,选项a)更可取(因此模板化是多余的...)
选项b)意味着输入可以是任何类型,而不与类A有任何继承关系。
当方法test()可以使用另一种类型B时,它将被使用。
class B
{
}

这些结论是否正确?

并且类型为A-A3。


1
programmers.SE 更适合概念性问题。 - outis
4个回答

3

你是正确的。

为了充分利用多态性并排除冗余代码,应该优先选择选项A。如果您想让您的方法也可用于其他类,则使用选项B,尽管即使在这种情况下,最好也重载函数而不是使用模板。

假设您有两个指针A * aA1 * a1。 如果您在aa1上同时调用您的方法,则在编译期间将创建两个方法,一个采用A *参数,另一个采用A1 *参数。这是无用的,因为多态性可以处理只传递A *参数的情况。

此外,还有一个好处,就是您可以将实现与声明分开,这在模板的情况下是不可能的。


1

在这种情况下,选项a似乎更方便,正如您所得出的结论。我会给出一个答案作为您的结论:“处理基类的方法实际上将处理所有派生类,而这里的意图适合这种情况”。


1

模板允许您对不相关的类执行相同的操作。

您还可以使用适配器,因此您可以为A和B(不相关)创建派生自公共适配器并执行所需功能的适配器。

模板的主要目的通常是将相同的逻辑应用于主要不相关的类型,因为例如,您以某种方式操作类型集合,而算法与您如何操作它们有关。


谢谢,我很高兴我的假设是正确的...我在某个库中看到了这段代码,没有考虑这种方法是正确的... - justik

0

这里的选择不仅仅是一个风格选择:选项A提供运行时多态性,而选项B提供编译时多态性。你没有提供足够的信息来确定在这种情况下哪个更好。

一般来说,我的建议是仅当您想使用A*调用test时才使用选项A。随之而来的假设是A可能是一个抽象基类(或至少具有虚函数)。在那种情况下,甚至不可能合理地使用选项B,希望test将由在A*上调用一些虚函数以产生所需效果的方式组成(而不是以复杂的方式进行dynamic_cast)。

然而,如果您不打算使用 A* 调用 test,那么选项 B 通常更好:您允许该函数与任何类型一起使用,并且从调用虚函数中减少了运行时开销(这可能是可以忽略的,但仍然存在)。它还使该函数具有更多自由度:例如,如果需要,它可以创建另一个 TType,如果将其传递给抽象基类的指针,则更难实现。最后,您可以使用模板特化和静态断言等功能,如果确实需要。

总之,问题应该是“我是否想在此类中使用运行时多态性?”;一旦您做出决定,这两个选项之间的选择就变得明显了。

(顺便说一下,在模板的情况下,您可能希望传递 TType const&,而不是 TType const*。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接