Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.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++;_C++_Abstract Class_Header Files - Fatal编程技术网

C++ 混凝土类的单独头文件-C++;

C++ 混凝土类的单独头文件-C++;,c++,abstract-class,header-files,C++,Abstract Class,Header Files,背景 我有一个抽象类,类似 class IConverter{ public: virtual void DoConvertion() = 0; }; 将有许多具体的类只实现DoConvertion方法 将有许多这样的具体实施。我创建了一个头文件,比如CharacterConverter.h,它具有抽象类IConverter 问题 由于我的具体类只实现了DoConvertion方法,是否需要为每个具体类创建单独的头文件?我的意思是,是否需要为所有具体类创建ImageConver

背景

我有一个抽象类,类似

class IConverter{
    public:
    virtual void DoConvertion() = 0;
};
将有许多具体的类只实现DoConvertion方法

将有许多这样的具体实施。我创建了一个头文件,比如CharacterConverter.h,它具有抽象类IConverter

问题

由于我的具体类只实现了DoConvertion方法,是否需要为每个具体类创建单独的头文件?我的意思是,是否需要为所有具体类创建ImageConverter.h、TextConverter.h等等?所有这些头文件都将包含与IConverter抽象类相同的代码


有什么想法吗?

你可能会从两方面得到答案

我想说,对于任何简单的转换器,将所有转换器都放在一个.h/.cpp对中就足够了,将每个转换器拆分成一个对就太过分了。我认为在这种情况下,维护大量文件与维护单个文件中的一组方法之间的权衡是值得的


复杂的转换可能需要自己的文件对。

这不是必需的。这基本上是一种判断

如果每个类的实现都很简单,那么可以将它们全部放在一个.h和一个.cpp中

如果实现稍微长一点,那么为每个实现使用单独的.h和.cpp文件可能会更干净

为每个类使用不同的.h/.cpp的一些优点:

  • 它将保持代码的组织和干净
  • 减少了编译工作:其中一个实现中的更改不需要重新编译所有其他实现
  • 更快的编译时间:多个编译器可以同时编译多个文件,例如VisualStudio的/MP开关。有了几个文件,编译速度会更快
  • 其他文件只能包含他们需要的内容,而不能包含所有内容
  • 更快的链接时间:由于增量链接,链接时间将减少
  • 使用版本控制,您可以只查看对特定派生类的更改,而不必查看对大量1.h/.cpp文件所做的所有更改,以便在特定派生类中找到该更改

创建对象需要具体类的定义,所以需要将这些定义放在.h文件中的某个位置。你把它们放进哪个文件取决于你。

最好的答案是什么更容易阅读。一个长源文件对于您和其他程序员来说将很难遵循。另一方面,许多小的(半屏幕全屏幕)源文件也同样糟糕

> P> >根据您设计的其余部分,您可以考虑的是工厂,其中抽象类有一个静态方法(或多个静态方法,取决于您如何实现它),构建适当的子类并将其作为ICONVIERT *返回。这样,您就可以只在头文件中公开抽象定义,并将所有具体的类定义和实现与超级类实现一起放在一个.cpp文件中。如果您的子类很大,这会变得有点笨拙,但是对于较小的类,它会减少您必须管理的文件数量

但是,正如其他人所指出的,这最终是一个判断。唯一的性能问题将与编译有关;更多的cpp文件可能需要(稍微)更长的时间来编译,更多的头文件可能会增加依赖性分析。但并不要求每个头文件都有匹配的cpp,反之亦然

根据评论,我建议采用如下结构:

IConverter.h==>IConverter的定义
Converters.h==>所有子类的定义
IConverter.cpp==>包含IConverter.h和converter.h,包含IConverter抽象功能的实现(静态工厂方法和任何可继承的功能)
textconverter.cpp、ImagerConverter.cpp等==>将每个子类的cpp文件分开,每个子类包含IConverter.h和converter.h


这允许您仅在使用factory和通用功能的任何客户端中包含IConverter.h。将所有其他定义放在一个标题中,如果它们基本相同,则可以进行合并。单独的cpp文件允许您利用Brian提到的编译器优势。您可以像前面提到的那样将子类定义内联到头文件中,但这并不能真正为您带来任何好处。当涉及到诸如内联之类的优化时,您的编译器通常比您更聪明

创建接口类的一个要点是,客户机可以依赖于抽象接口而不是具体的实现,然后您可以在不影响客户机的情况下自由更改实现


将具体声明放在与接口声明相同的头文件中会使这一问题迎刃而解,因此,现在如果您更改具体类的实现细节,您的客户机将需要重新编译。

您最好使用工厂或函数指针

然而,我想到的一种特别讨厌的方法是使用宏来声明您的具体类。例如:

在IConverter.h的底部包括以下宏

#define DECLARE_CONVERTER_CLASS(CLASS_NAME) \
class CLASS_NAME : public IConverter\
{ \
    public: \
    CLASS_NAME() {} \
    virtual void DoConversion(); \
}; \
然后在MyConverter1.cpp中

DECLARE_CONVERTER_CLASS(MyConverter1)

virtual void MyConverter1::DoConversion()
{
    ...
}

恶心:-)

在一个不相关的样式点上,我可能会使用实际的单词“Conversion”(如DoConversion)作为方法名。DoConvertion不是方法名。我把它放在这里是为了展示样品。:)还要使IConverter的析构函数虚拟化。即使你只是内联定义。谢谢。具体类的实现要长一些。所以如果我把它放在头文件中,我会担心性能的差异。谢谢。如果我将具体类放在头文件中而不为每个类创建CPP文件,会不会产生任何性能问题?我将只在一个地方包括所有具体的课程
DECLARE_CONVERTER_CLASS(MyConverter1)

virtual void MyConverter1::DoConversion()
{
    ...
}