g++ 两个关于头文件编译问题
好吧,不得不说Professor Demko的C++ for FE 的project真是可以加速学习C++的好方法。当年本科时候在李文新老师的课上学C++最后也只是完成了POJ上《魔兽世界》的大作业,而且只考虑了下派生类、友类和虚构函数。其他东西,呵呵,早都忘了噜。
好了,废话不多说,开始讨论问题。
在 terminal中用g++编译C++文件,遇到两个主要的问题,中文网页中很少有所讨论。卤煮在stackoverflow上倒是看到了不少这样的讨论,果然程序员的英文水平都很高>w<
- 头文件中类的构建函数
楼主将一个正态函数生成及相关计算的类写入了一个头文件,该头文件在其他文件和主文件中都会被调用。
头文件的代码如下
1 #ifndef _NORMDISTINTEGRAL_H__ 2 #define _NORMDISTINTEGRAL_H__ 3 4 /* Generate Normal Distribution */ 5 6 #include <iostream> 7 #include <cmath> 8 9 const double PI = 3.1415926; 10 11 class MyNormDist 12 { 13 double mean; // the mean of Normal Distribution 14 double std_v; // standard deviation 15 public: 16 MyNormDist(double mean_, double std_v_); 17 ~MyNormDist(); 18 double Norm_pdf(double x); // probability density function 19 double Norm_cdf(double x); // cumlative distribution function 20 double Norm_igral(const double& low_b, const double& up_b); // integral 21 }; 22 23 #endif
与头文件同名的cpp文件中代码如下,主要对头文件类中的函数内容进行编写。
1 #include "NormDistIntegral.h" 2 3 using namespace std; 4 5 MyNormDist::MyNormDist(double mean_, double std_v_) 6 { 7 mean = mean_; 8 std_v = std_v_; 9 } 10 11 //MyNormDist::~MyNormDist(){} 12 13 /* 省略以下描述函数代码 */
单独对该cpp文件进行g++编译是完全没有问题的。但是对主文件进行编译时(关联其他o文件),遇到了如下的问题。
Undefined symbols for architecture x86_64:
"MyNormDist::~MyNormDist()", referenced from:
___tcf_2 in CashFlow.o
___tcf_1 in BSE.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
好吧,他说我析构函数没有找到。stackoverflow上给的解答是,析构函数的函数内容也应该在cpp文件中写出,而不应该省去。因为头文件仅仅是对类及类中得变量、函数进行声明。实际调用还是应该从cpp文件中调用的,因此就算析构函数没有具体内容,也应该在cpp文件中写出,即把上一段代码中第11行的注释dashes给去掉。
references:http://stackoverflow.com/questions/11488486/undefined-symbols-for-architecture-x86-64-compiling-inherited-class?rq=1
2. 文件调用
楼主还为主文件编写了个cpp文件getCMT.cpp,其中包含函数 getCMT() 以冀在主文件main.cpp和CashFlow.cpp中直接调用。可是编译主文件时,又报出了如下的错误
ld: duplicate symbol getCMT()
in CashFlow.o and main.o for architecture x86_64
collect2: ld returned 1 exit status
好吧,stackoverflow上给出的答案是,在多个其他cpp文件中直接用引用cpp文件时候,该cpp文件因为被多个文件include,这些文件的o文件都会得到这个函数的复制件。C++是禁止对同一函数进行多次定义的,linker可能会对此报错。
如何解决了,建议将这些函数体写到一个cpp文件中,并建立一个与cpp文件同名的的头文件,头文件仅仅对cpp文件中得函数进行声明。在其他文件中需要引用该函数的时候,include该头文件即可。
Reference:http://stackoverflow.com/questions/9299676/ld-duplicate-symbol