简体   繁体   English

C ++,继承与多态

[英]C++, inheritance vs polymorphism

I have a little bit "philosophical" question. 我有点“哲学”的问题。 There is a class A 有一个A级

class A
{

}

and classes A1, A2, A3 derived from A. 和A1,A2,A3类来自A.

class A1 : public A
{
}

class A2 : public A
{
}

class A3 : public A
{
}

and one static method processing objects A - A3. 和一个静态方法处理对象A-A3。 Which variant should be preferred? 应该首选哪种变体?

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

or 要么

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

In my opinion, in this case, the option a) is preferable (so the templatization is redundant...) 在我看来,在这种情况下,选项a)是更可取的(所以模板化是多余的......)

The option b) means that the input can be any type, that is not in any inheritance relationship to the class A. 选项b)表示输入可以是任何类型,与A类没有任何继承关系。

It would be used in the case where the method test() can work with another type B 它将用于方法test()可以与另一种类型B一起使用的情况

class B
{
}

and types A-A3. 和类型A-A3。

Are these conclusions correct or not? 这些结论是否正确?

You are right. 你是对的。

To fully take advantage of polymorphism and exclude redundant code, option A should be prefered. 为了充分利用多态性并排除冗余代码,应优先选择选项A. Use option B if you want your method to also be available for other classes, although even then it's probably better to overload the function rather than using a template. 如果您希望您的方法也可用于其他类,请使用选项B,尽管这样可能更好地重载函数而不是使用模板。

Say you have two pointers A* a and A1* a1 . 假设你有两个指针A* aA1* a1 If you call your method on both a and a1 , two methods will be created during compilation, one taking a A* parameter, the other one a A1* parameter. 如果在aa1上调用方法,则在编译期间将创建两个方法,一个采用A*参数,另一个采用A1*参数。 This is useless, since polymorphism can handle just passing an A* parameter. 这是无用的,因为多态可以只处理传递A*参数。

Also, there is the advantage that you can separate the implementation from the declaration, which is not possible in the case of templates. 此外,还有一个优点是您可以将实现与声明分开,这在模板的情况下是不可能的。

Option a seems more convenient in this case as you concluded. 在你总结的情况下,选项a在这种情况下似乎更方便。 I would given an answer as your conclusion: "a method processing the base class will actually process all derived classes and the intention here suits to this case". 我会给出一个答案作为你的结论:“处理基类的方法实际上将处理所有派生类,这里的意图适合于这种情况”。

The template allows you do to the same things with unrelated classes. 该模板允许您对不相关的类执行相同的操作。

You can also use adapters so you would make adapters for A and for B (unrelated) that derive from a common adapter and perform the functionality you want. 您还可以使用适配器,以便为A和B(不相关)创建适配器,这些适配器派生自通用适配器并执行所需的功能。

The main purpose of a template normally is to apply the same logic to primarily unrelated types because, for example, you are manipulating collections of types in some way and the algorithm relates to how you manipulate them. 模板的主要目的通常是将相同的逻辑应用于主要不相关的类型,因为,例如,您以某种方式操作类型集合,并且算法与您如何操作它们有关。

The choice here is not (only) a stylistic one: option A provides runtime polymorphism, while option B provides compile-time polymorphism. 这里的选择不是(仅)一个风格的选项:选项A提供运行时多态性,而选项B提供编译时多态性。 You have not supplied us with enough information to figure out which one is preferred in this case. 在这种情况下,您还没有向我们提供足够的信息来确定哪一个是首选的。

In general, my advice would be to use option A if and only if you want to call test with an A* . 一般来说,我的建议是当且仅当你想用A*调用test时才使用选项A. With this comes the assumption that A is probably an abstract base class (or at least has virtual functions). 有了这个假设, A可能是一个抽象基类(或者至少具有虚函数)。 In that case it is not even possible to sanely use option B, and hopefully test will consist of calling some virtual functions on the A* to a desired effect (as opposed to dynamic_cast ing it in nasty ways). 在这种情况下它不是甚至可以使用三立选项B,并希望test将包括呼吁一些虚拟函数的A*至所希望的效果(相对于dynamic_cast讨厌的方式荷兰国际集团它)。

However, if you are not ever going to call test with an A* , option B is generally better: you allow for the function to be used with any type, and there is less runtime overhead from calling virtual functions (which may be negligible, but none the less). 但是,如果您不打算使用A*调用test ,则选项B通常更好:允许该函数与任何类型一起使用,并且调用虚函数的运行时开销较少(可以忽略不计,但是,没有。 It also gives the function somewhat more freedom: for instance, it can create another TType if necessary, which is harder if you pass it a pointer to an abstract base class. 它还为函数提供了更多的自由:例如,它可以在必要时创建另一个TType ,如果您将指针传递给抽象基类,则会更难。 Finally, you get to use features like template specialisations and static asserts if you really want to. 最后,如果你真的想要,你可以使用模板特化和静态断言等功能。

All in all, the question should be "Do I want to use runtime polymorphism with this class?"; 总而言之,问题应该是“我是否想在此类中使用运行时多态性?”; the choice between these two becomes obvious once you decide that. 一旦你决定,这两者之间的选择就变得很明显了。

(By the way, in the case of the template, you probably want to pass TType const& , not TType const* .) (顺便说一句,在模板的情况下,您可能希望传递TType const& ,而不是TType const* 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM