函数声明顺序在头文件中是否重要?

时间:2013-11-08 12:15:57

标签: c++ c++11 declaration

我想知道标题中函数的声明顺序是否具有重要性。

让我们想象一下:我有两个使用相同标头定义的项目,并且由于一些不明原因必须复制标题。并且这些标题在声明函数顺序方面不一样。

所以我的第一个项目的标题是:

class A {
  someFunctionA();
  someFunctionB();
}

和第二个项目中的标题:

class A {
  someFunctionB();
  someFunctionA();
}

现在,如果我在第二个项目中使用第一个项目中创建的实现(如动态库或其他),会发生什么?

我知道我应该为两个项目使用相同的头文件定义,我只是想知道编译器是否会为函数使用某种堆栈或者将它们重新排序。

3 个答案:

答案 0 :(得分:8)

严格地说,除非两个类定义相同(在预处理后定义为由相同的标记序列组成),否则您有未定义的行为。

在实践中,只要两个类的内存布局保持不变,就可能不会出现任何问题。添加,删除或重新排序非虚拟成员函数不会影响布局。对基类,数据成员或虚拟成员函数执行此操作将影响布局,并可能导致可怕的不可思议的错误。

由于无法防止不兼容的更改,我强烈建议您不要这样做。要么找到在项目之间共享相同类定义的方法,要么完全分支它并分别维护每个分支。

答案 1 :(得分:2)

即使您共享相同的头文件,您仍然可以通过版本控制遇到此问题。例如,您的项目可能已针对动态库的版本1进行了编译。然后,您无需重新编译项目即可运送库的第2版。在这种情况下,您需要确保库不会破坏二进制兼容性。

这里列出了维护二进制兼容性能做什么和不能做什么的好清单:http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++#The_Do.27s_and_Don.27ts

要回答您的问题,您可以重新订购非虚拟功能,但不能重新订购成员变量或虚拟功能。

答案 2 :(得分:0)

函数声明顺序很重要,尤其是函数声明具有默认参数

例如在下面的函数声明中,如果更改声明顺序,则编译为您提供 - 缺少默认参数错误。原因是编译器允许您将函数声明与默认参数分隔在同一范围内但它应该从 RIGHT到LEFT (默认参数)和从 TOP到BOTTOM (函数声明默认参数的顺序)。

//declaration
void function(char const *msg, bool three, bool two, bool one = false);
//void function(char const *msg, bool three = true, bool two, bool one); //Error 
void function(char const *msg, bool three, bool two = true, bool one); // OK
void function(char const *msg, bool three = true, bool two, bool one); // OK

int main() {
    function("Using only one Default Argument", false, true);
    function("Using Two Default Arguments", false);
    function("Using Three Default Arguments");
    return 0;
}

//definition
void function(char const *msg, bool three, bool two, bool one ) {
    std::cout<<msg<<" "<<three<<" "<<two<<" "<<one<<std::endl;
}