具体类的单独头文件 - C++
背景
我有一个抽象类,类似于
class IConverter{
public:
virtual void DoConvertion() = 0;
};
There will be much具体类,它们只实现 DoConvertion 方法。
class TextConverter : public IConverter{
public:
virtual void DoConvertion(){
// my code goes here
}
};
class ImageConverter : public IConverter{
public:
virtual void DoConvertion(){
// my code goes here
}
};
这样的具体实现还有很多。 我创建了一个头文件,例如 CharacterConverter.h,它具有抽象类 IConverter。
问题
由于我的具体类只实现了DoConvertion方法,是否需要为每个具体类创建单独的头文件? 我的意思是是否需要为所有具体类创建 ImageConverter.h、TextConverter.h 等? 所有这些头文件都将包含相同的代码,例如 IConverter 抽象类。
有什么想法吗?
Background
I have an abstract class, something like
class IConverter{
public:
virtual void DoConvertion() = 0;
};
There will be many concrete classes which just implements DoConvertion method.
class TextConverter : public IConverter{
public:
virtual void DoConvertion(){
// my code goes here
}
};
class ImageConverter : public IConverter{
public:
virtual void DoConvertion(){
// my code goes here
}
};
There will be many concrete implementation like this. I have created a header file say, CharacterConverter.h which has the abstract class IConverter.
Question
Since my concrete classes just implement the DoConvertion method, is it required to create separate header files for each concrete class? I mean is it required to create ImageConverter.h, TextConverter.h and so on for all concrete classes? All these header files is going to contain the same code like IConverter abstract class.
Any thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
根据设计的其余部分,您可能会考虑一个工厂,其中您的抽象类具有一个静态方法(或多个静态方法,具体取决于您的实现方式),该方法构造适当的子类并将其作为 IConverter* 返回。 这样,您可以仅公开头文件中的抽象定义,并将所有具体类定义和实现以及超类实现一起放在单个 .cpp 文件中。 如果您的子类很大,这会有点麻烦,但对于较小的类,它会减少您必须管理的文件数量。
但是,正如其他人指出的那样,这最终是一个判断。 唯一的性能问题与编译有关; 更多的 cpp 文件可能需要(稍微)更长的时间来编译,更多的头文件可能会增加依赖性分析。 但不要求每个头文件都有匹配的 cpp,反之亦然。
根据评论,我推荐这样的结构:
IConverter.h ==> IConverter的定义
Converters.h ==> 所有子类的定义
IConverter.cpp ==> 包括 IConverter.h 和 Converters.h,包含 IConverter 抽象功能的实现(静态工厂方法和任何可继承的功能)
TextConvter.cpp、ImagerConverter.cpp等==> 每个子类都有单独的 cpp 文件,每个文件都包含 IConverter.h 和 Converters.h
这允许您仅在使用工厂和通用功能的任何客户端中包含 IConverter.h。 将所有其他定义放在一个标头中可以让您合并(如果它们基本相同)。 单独的 cpp 文件允许您利用 Brian 提到的编译器优势。 您可以如上所述在头文件中内联子类定义,但这并不能真正为您带来任何好处。 当涉及到内联等优化时,您的编译器通常比您更聪明。
Something you might consider, depending on the rest of your design, is a factory, where your abstract class has a static method (or multiple static methods, depending on how you implement it) that constructs the appropriate subclass and returns it as an IConverter*. With this, you can expose only the abstract definition in the header file, and have all the concrete class definitions and implementations in a single .cpp file along with the super class implementation. This gets a bit unwieldy if your subclass are large, but with smaller classes it reduces the number of files you have to manage.
But, as others have pointed out, it's ultimately a judgment call. The only performance issues would be related to compiling; more cpp files might take (slightly) longer to compile and more header files might increase dependency analysis. But there's no requirement that every header file have a matching cpp and vice verse.
Based on the comments, I'd recommend a structure like this:
IConverter.h ==> definition of IConverter
Converters.h ==> definitions of all subclasses
IConverter.cpp ==> include IConverter.h and Converters.h, contain implementation of IConverter abstract functionality (static factory method and any inheritable functionality)
TextConvter.cpp, ImagerConverter.cpp, etc. ==> seperate cpp files for each subclass, each containing IConverter.h and Converters.h
This allows you to only include the IConverter.h in any clients that use the factory and generic functionality. Putting all the other definitions in a single header allows you to consolidate if they're all basically the same. Separate cpp files allow you to take advantage of the compiler benefits mentioned by Brian. You could inline the subclass definitions in header files as mentioned, but that doesn't really buy you anything. Your compiler is usually smarter than you are when it comes to optimizations like inline.
您可能会从两个方面得到答案。
我想说,对于任何简单的转换器,将它们全部放在单个 .h/.cpp 对中就足够了,将每个转换器分成一对就太过分了。 我认为在这种情况下,维护大量文件与维护单个文件中的一堆方法的权衡是值得的。
复杂的转换可能应该有自己的文件对。
You'll probably get answers both ways.
I'd say, for any trivial converters, having all of them in a single .h/.cpp pair is sufficient and that it's overkill to split every one into a single pair. I think the tradeoff of maintenance of lots of files vs. maintenance of a bunch of methods within a single file is worth it in this case.
Complex conversions probably deserve their own file pairs.
您将需要具体类的定义来创建对象,因此您需要将这些定义放入 .h 文件中的某个位置。 将它们放入哪个文件取决于您。
You will need definitions of the concrete classes to create objects, so you'll need to put those definitions into a .h file somewhere. Which file you put them in is up to you.
对此问题的最佳答案就是更容易阅读。 一份很长的源文件对于您和其他程序员来说将很难理解。 另一方面,许多微小的(半屏)源文件也同样糟糕。
The best answer to this is what's easier to read. One long source file is going to be difficult for you and other programmers to follow. On the other hand, many tiny (half screen-full) source files is just as bad.
使用工厂或函数指针可能会更好。
然而,我想到的一种特别令人讨厌的方式是使用宏来声明具体的类。 例如:
在 IConverter.h 的底部包含以下宏
然后在 MyConverter1.cpp 中
恶心:-)
You'd probably be better off using factories or function pointers.
However, one particularly nasty way that springs to mind is using a macro to declare your concrete classes. For example:
At the bottom of IConverter.h include the following macro
Then in MyConverter1.cpp
Yuck :-)
这不是必需的。 这基本上是一个判断。
如果每个类的实现都很简单,您可以将它们全部放在一个 .h 和一个 .cpp 中。如果
实现有点长,那么为每个类使用单独的 .h 和 .cpp 文件可能会更干净。
为每个类使用不同的 .h/.cpp 的一些优点:
It is not required. It's basically a judgment call.
If the implementation is simple for each class you can put them all in one .h and one .cpp
If the implementations are a bit longer, then it's probably cleaner to use a separate .h and .cpp file for each.
Some advantages of using a different .h/.cpp for each class:
创建接口类的要点之一是让客户端可以依赖抽象接口而不是具体实现,然后您可以自由更改实现而不影响客户端。
将具体声明放在与接口声明相同的头文件中可以解决这个问题,因此现在如果您更改具体类的实现细节,您的客户端将需要重新编译。
One of the main points of creating an interface class is so that clients can be depend on the abstract interface rather than the concrete implementation, and you are then free to change the implementation without impacting clients.
Putting the concrete declarations in the same header files as the interface declarations defeats this, so now if you change an implementation detail of a concrete class, your clients would need to re-compile.