6

我想知道标头中函数的声明顺序是否重要。

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

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

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

和第二个项目中的标题:

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

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

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

4

3 回答 3

8

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

实际上,只要两个类的内存布局保持不变,就可能不会有任何问题。添加、删除或重新排序非虚拟成员函数不会影响布局。对基类、数据成员或虚拟成员函数这样做会影响布局,并可能导致极其难以理解的错误。

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

于 2013-11-08T13:03:21.143 回答
2

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

在维护二进制兼容性方面可以做什么和不可以做什么的一个很好的列表在这里:http ://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++#The_Do.27s_and_Don.27ts

要回答您的问题,您可以重新排序非虚拟函数,但不能重新排序成员变量或虚拟函数。

于 2013-11-08T13:14:25.053 回答
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;
}
于 2014-06-18T13:57:55.380 回答