项目编译时的obj文件链接时有可能出现问题的地方。
编译器将把每个cpp文件编译成 obj ,每个类、结构体中的变量都将在编译后形成 偏移值。
所以若同一项目下的两个cpp文件中都包含 class A,而两个A中的成员变量不同的话,链接时,将分别按照自身的A类形式形成偏移地址,将会出错。
1 x.cpp
2 class A
3 {
4 public:
5 int b, a;
6 };
7
8 void setVal(A& val, int a, int b)
9 {
10 val.a = a;
11 val.b = b;
12 }
1 main.cpp
2
3 #include <iostream>
4
5 class A
6 {
7 public:
8 A()
9 {
10 a = 0;
11 b = 0;
12 }
13
14 int a, b;
15 };
16
17 void setVal(A& val, int a, int b);
18
19 void main()
20 {
21 A x;
22 setVal(x, 5, 10);
23 std::cout<<x.a<<"\t"<<x.b<<std::endl;
24 }
25
26 //输出结果为:10 5
头文件中存在 具体函数实现、静态成员变量赋值 的处理办法。
1. 若一定要包含,函数使用 inline 内联。
静态成员变量使用 __declspec(selectany) 修饰。
否则,当多个 cpp 包含此 头文件 时,编译器会报错“找到一个或多个多重定义的符号”。每个cpp包含时都将执行函数实现,静态变量初始化,将会出现重复定义报错。
1 class B
2 {
3 public:
4 static int n;
5 int a, b;
6
7 void Func1()
8 {
9 //具体实现。此处编译器自动内联将不会报错
10 }
11
12 void Func2();
13 };
14
15 __declspec(selectany) int B::n = 0;
16
17 inline void B::Func2()
18 {
19 int x = a;
20 a = b;
21 b = x;
22 }
2. 还有一种处理办法,即使用模板技术,即可实现。模板自动在第一次初始化时记录,以后的将自动用第一次的处理。
1 template<typename T>
2 class B
3 {
4 public:
5 static T n;
6 int a, b;
7
8 void Func1()
9 {
10 //具体实现。此处编译器自动内联
11 }
12
13 void Func2();
14 };
15
16 template<typename T>
17 T B<T>::n;
18
19 template<typename T>
20 void B<T>::Func2()
21 {
22 int x = a;
23 a = b;
24 b = x;
25 }
防止头文件多次加载的方法。
使用宏
1 #ifndef ABCDEFG
2 #define ABCDEFG
3 #pragma once //vs专用
4 //具体头文件内容
5 #endif