window系统下编译多个cpp与h文件只需在工程中导入即可,然而linux系统下程序的编译往往以文件为单位,并不像Windows下可以在工程环境中运行,所以可以使用Makefile将多个文件链接起来进行编译。
下面是要测试的情形
我是在home/pi目录下创建的文件,名为testmake
cd 进入该文件,在里面创建要测试的程序文件,如下所示,三个h文件,三个cpp文件,还有一个makefile文件。
这里的a.cpp和a.h,b.cpp和b.h为两组相应的头文件和程序文件,main.cpp为主程序,Main.h负责创建一个抽象类,供a.h和b.h继承,代码如下
Main.h如下所示
#pragma once
#include <iostream>
class Main
{
public:
virtual void print()=0;
int m_A;
int m_B;
};
里面有一个函数,两个变量,virtual关键字用到了多态的知识,这里不细说。
a.h如下所示,继承Main.h中的Main类。
#pragma once
#include <iostream>
#include "Main.h"
class A:public Main
{
public:
A(int a,int b);
virtual void print();
};
a.cpp如下所示
#include "a.h"
A::A(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
void A::print()
{
std::cout << this->m_A << std::endl;
std::cout << this->m_B << std::endl;
}
同理b.h和b.cpp如下所示
#pragma once
#include <iostream>
#include "Main.h"
class B:public Main
{
public:
B(int a,int b);
virtual void print();
};
#include "b.h"
B::B(int a,int b)
{
this->m_A = a;
this->m_B = b;
}
void B::print()
{
std::cout << "m_A = " << this->m_A << std::endl;
std::cout << "m_B = " << this->m_B << std::endl;
}
主程序main.cpp如下所示
#include "a.h"
#include "b.h"
int main()
{
A a(1,2);
a.print();
B b(3,4);
b.print();
return 0;
}
以上是本次测试的全部程序。他们的关系是:主程序运行首先需要找到a.h和b.h,这里涉及到linux系统头文件搜寻机制,现在只要在同级目录下就可以找到,进入main函数,实例化a并运行print函数和实例化b并运行print函数,所以他们要找到a.cpp和b.cpp,这里就涉及到文件链接,Windows下是工程自动链接,linux需要自己手动链接,所以这时候就需要makefile文件。
makefile如下
.PHONY: run clean
run:go
a.o:a.cpp Main.h a.h
g++ -c a.cpp -o a.o
b.o:b.cpp Main.h b.h
g++ -c b.cpp -o b.o
main.o:main.cpp a.h Main.h b.h
g++ -c main.cpp -o main.o
go:main.o a.o b.o
g++ -o go main.o a.o b.o
./go
clean:
rm -f *.o go
下面来解释啥意思
.PHONY: run clean
.PHONY是伪指令的意思,类似于cpp中的define,设置伪指令就可以用这个指令运行我们真正要运行的指令,这里有run和clean,最后的效果就是运行run和clean就可以自动执行他们后面的g++和rm指令。
makefile的规则是
目标文件:链接文件
(tab)要运行的指令
run:go中的go是我们要获得的最终文件,即名为go的可执行文件,类似于.out,在这中间我们要获得能够执行go文件的所有中间文件即.o文件,每一个cpp文件都要生成一个.o文件
每一个小分支如下
a.o:a.cpp Main.h a.h
g++ -c a.cpp -o a.o
这里是为了得到a.o文件,所以冒号后面跟着生成a.o文件所需要的文件,即生成a.o文件需要a.cpp,Main.h,a.h,这里涉及到继承的问题,所以生成a.o和b.o都需要Main.h
go:main.o a.o b.o
g++ -o go main.o a.o b.o
./go
这一句是用来生成go文件的,要用到前面生成的所有o文件,这样就可以链接在一起。最后执行go文件
效果如下
最后运行成功。
clean伪指令是用来执行清除o文件和go文件功能
make clean
这里是比较简单的makefile版本,只是单纯的几个头文件与源文件的组合,但是方便性不是很好,因此又写了一篇关于makefile的博客,里面有关于完整makefile案例的分析与检测测试