And*_*rea 29 c++ constructor header-files
我可以在类.h文件或实现文件.cpp中定义类构造函数的主体.就编译器在特定项目中而言,这两种样式可能是相同的(项目对我来说意味着DLL).同样适用于任何成员函数:它们可以在头文件中定义,也可以在那里声明,然后在cpp文件中定义.
但是,我发现,如果我需要包括在不同的项目,例如类的头文件(一个或多个)(这意味着最终使用该头文件中的代码不同的最终DLL),则具有在头文件中的实际的实现会导致一些头痛在编译时(不是在链接...我甚至没有达到这一点).为什么?好吧,我不会详细说明,但编译器显然试图解决其他头文件等中可能定义的所有函数,迫使可怜的开发人员开始引入各种头文件等.
是不是总是最好保持头文件没有任何实现,只是将它们用于'声明'?这样可以更容易地将它们包含在多个项目中,而不必携带大量额外的垃圾.
你对此有何看法?
Tho*_*mas 28
保持标头不受实现的影响,除非您希望实现内联(例如,琐碎的getter/setter).当然,除非他们是模板.
我认为没有理由为构造函数做一个例外.将它们放在.cpp文件中.
Ser*_*nov 26
需要注意的一点是,如果在头文件中定义了一个成员函数,它必须位于类体内,或者必须明确标记为inline.换句话说,在头文件中执行此操作是完全错误的:
class A {
public:
A();
};
A::A() {
// constructor body
}
Run Code Online (Sandbox Code Playgroud)
这是错误的原因是因为它会使编译器在每个编译单元中包含定义,而显然任何函数只能定义一次.以下是做同样事情的正确方法:
class A {
public:
inline A();
};
inline A::A() {
// constructor body
}
Run Code Online (Sandbox Code Playgroud)
要么:
class A {
public:
inline A() { // inline isn't required here, but it's a good style
// constructor body
}
};
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,构造函数都是内联的.使其成为常规外联函数的唯一正确方法是在实现文件中定义它,而不是在头文件中定义它.这是这两种方法之间最重要的区别.
现在,值得注意的是内联是一种优化.并且一如既往地进行优化,最好避免它们,直到证明有必要.在内联可能导致的其他问题中,存在兼容性问题:如果更改未内联的函数的主体,则只需重新编译定义它的单元,并且每个人都立即开始使用新实现.使用内联函数,您需要重新编译包含相关标题的每个单元,这可能很麻烦,尤其是如果标题由不同的人在不同的项目中使用.
换句话说,尽可能使用常规的外部定义,直到通过分析特定函数调用是性能瓶颈来证明它为止.这个规则的唯一合理的例外是微不足道的setter和getter,即使使用它们也最好小心 - 有一天它们可能变得非常重要,这将意味着大量的重新编译和兼容性破坏.