Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么时候应该使用模板而不是继承,反之亦然?_C++_Templates_Inheritance - Fatal编程技术网

C++ 什么时候应该使用模板而不是继承,反之亦然?

C++ 什么时候应该使用模板而不是继承,反之亦然?,c++,templates,inheritance,C++,Templates,Inheritance,在许多情况下,这个问题甚至不会问自己,因为有时候继承提供了模板无法提供的必要特性。例如,当我需要通过一个基类型(多态性)处理不同的类型时,我需要使用继承 但是,在某些情况下,这个问题可以通过继承和模板来解决 以策略模式为例,如代码某些部分的参数化: 文件解析器的一种解决方案如下所示: class FileParser { //... public: void Parse(ParsingAlgorithm* p); //... } void FileParser::

在许多情况下,这个问题甚至不会问自己,因为有时候继承提供了模板无法提供的必要特性。例如,当我需要通过一个基类型(多态性)处理不同的类型时,我需要使用继承

但是,在某些情况下,这个问题可以通过继承和模板来解决

以策略模式为例,如代码某些部分的参数化:

文件解析器的一种解决方案如下所示:

class FileParser
{
   //...
   public:
      void Parse(ParsingAlgorithm* p);
   //...
}

void FileParser::Parse(ParsingAlgorithm* p)
{
   m_whatevertypeofvaluesineed = p->Parse(whateverparametersyouneed);
}
其中ParsingAlgorithm是一个抽象基类,它提供了一些基本方法,需要由喜欢为FileParser类实现特定解析器的人继承

但是,使用模板也可以轻松实现这一点:

template <class Parser>
class FileParser
{
   //...
   public:
      void Parse()
      {
           m_whatevertypeofvaluesineed = m_parser.Parse(whateverparametersyouneed);
      }

   private:
      Parser m_parser;
   //...
}
模板
类文件解析器
{
//...
公众:
void Parse()
{
m_whatevertypeofvaluesineed=m_parser.Parse(whateverparametersyouneed);
}
私人:
解析器m_解析器;
//...
}
是否有一些通用规则可以用来决定是使用模板还是使用继承?或者我应该尽可能地使用模板,以避免虚拟函数之类的运行时开销?

模板提供编译时多态性,而不是继承提供的运行时多态性。如果可以,我更喜欢使用模板


这篇文章对它进行了详细的解释。

我的建议是在这种情况下都不使用,而是对每种文件类型使用单独的函数

    Stream stream = open(filepath);

    Image image = ParseBMP(stream);
    // ...or
    Image image = ParseJPG(stream);

不需要让事情变得更复杂。

如果您在编译时知道要操作哪些对象,那么带模板的静态多态性通常是最快的方法,它生成的代码更简洁(不需要显式继承)。它也可以更通用,因为您不受强类层次结构的限制

如果您想要运行时多态性,那么您别无选择,只能使用指针、继承和虚拟函数的轻微开销

我个人的看法是:

  • 尽可能使用模板,这很舒服
  • 使用继承对代码进行因式分解(但不要使用异构集合),但要小心切片
  • 不要担心虚拟呼叫的性能问题
  • 有时,您别无选择,希望异构集合在使用指针的痛苦中徘徊

模板通常在运行时性能更高,因为在编译时需要做更多的工作。另一方面,它们可能更复杂,因此难以书写和理解。因此,最好尽可能在不使整个解决方案过于复杂的情况下使用它们


对于您的示例,它们在功能上并不完全相同:第一个变体允许并要求您在运行时创建解析器实例,而第二个变体要求程序员在编写代码时选择解析器。

您是对的,但是我的例子应该是一个快速的例子,说明在这种情况下“继承与模板”的问题可能会出现。我不同意。使用不同的函数是反对开闭原则的,以前从未听说过这个原则,但对我来说这似乎有点邪恶