工欲善其事,必先利其器。学习编程语言也一样,首先得搭建好编程学习环境。任何一门语言的学习之初,都应该搭建好环境且准备好学习文档,在遇到任何问题时能够及时查询文档,在不断的遇到问题、解决问题、遇到问题、解决问题中成长。当然,这也是一个经验积累的过程。
明年这个时候就该找工作了,于是打算学一下C++,首先想到的是要搭建编程环境及准备好C++帮助文档。我所使用的系统为Ubuntu,编程环境包括:gcc、g++、make,分别通过apt-get install安装即可。或者直接安装build-essential,它包含了一整套的工具。
安装语句如下:
apt-get install gcc
apt-get install g++
apt-get install make
第二部就是要准备C++帮助文档。GNU GCC 提供了一份 C++ 标准库的文档,可以在http://gcc.gnu.org/mirrors.html中下载。具体的路径是: libstdc++/doxygen/libstdc++-man-xxxxxx.tar.bz2,可找一个最新日期的下载。展开包之后将
man/man3 中的所有文件拷贝到系统上已经存在的一个 man/man3 目录中即可使用。如下语句所示:
tar xvf libstdc++-man.20111215.tar.bz2
cp -rf ./man3/* /usr/share/man/man3/
这样,C++的编程环境和帮助文档就安装好了。下面就可以开始C++语言Hello World的编写了。
C++语言的编译推荐使用Makefile进行编译。当然单个文件的编译可以g++ --help查看。假设有一个类A,其源文件为a.h和a.cpp以及一个调用A的main.cpp文件。首先应该对每一个Cpp文件进行单独编译,然后在链接为可执行文件。
g++ -c a.cpp // 生成a.o
g++ main.cpp a.o //生成可执行文件a.out
采用对每一个Cpp文件进行编译的方式在文件量比较少时还可以手动完成,当一个工程代码量逐渐变大,文件数目逐渐变多时,再这样手动完成编译或许就不那么容易了。好在Linux下有一个强大的make工具,能够协助程序猿完成代码的自动编译。下面来看一个简单的Makefile例子。Makefile文件应该和程序源文件在同一个目录。
CC = g++
CPPFLAGS = -g -Wall
OBJS = main.o \
item_base.o \
bulk_item.o
all : main
# 无视all文件存在与否,按正常的makefile语法解析
.PHONY : all
# 使用所有的*.o文件生成可执行文件 $@表示main,$^表示$(OBJS)
main : $(OBJS)
$(CC) -o $@ $^
# 于任何.o为扩展名的文件相匹配,并且这些文件总是依赖于.cpp的文件
.cpp.o:
$(CC) -c -o $@ $^ $(CPPFLAGS)
clean:
rm -rf *.o
rm main
这样仅需要在源程序的当前目录下执行make命令,就能够自动生成可执行文件代码main以上Makefile文件所涉及的cpp源文件包括item_base.h、item_base.cpp、bulk_item.h、bulk_item.cpp和main.cpp文件,是C++ Primer里面的一个小例子。其关系是item_base是一个类,而bulk_item是item_base的派生类。main.cpp为一个包含main方法的cpp文件,表示程序的入口。
各部分源代码如下:
item_base.h
#ifndef ITEM_BASE_H_
#define ITEM_BASE_H_
#include <string>
class item_base {
public:
item_base();
item_base(std::string);
virtual ~item_base();
std::string book();
virtual double net_price(int num) {
return 1.1 * num;
}
virtual item_base* clone() const {
return new item_base(*this);
}
private:
std::string isbn;
};
#endif
item_base.cpp
#include "item_base.h"
item_base::item_base() {}
item_base::item_base(std::string s) {
isbn = s;
}
item_base::~item_base() {}
std::string item_base::book() {
if (isbn.empty())
return "isbn 0001";
else
return isbn;
}
bulk_item.hX
#ifndef BULK_ITEM_H_
#define BULK_ITEM_H
#include "item_base.h"
class bulk_item : public item_base {
public:
bulk_item();
bulk_item(float);
virtual ~bulk_item();
double net_price(int num);
bulk_item* clone() const {
return new bulk_item(*this);
}
private:
float zekou;
};
#endif
bulk_item.cpp#include "bulk_item.h"
bulk_item::bulk_item() {}
bulk_item::bulk_item(float zk) {
zekou = zk;
}
bulk_item::~bulk_item() {}
double bulk_item::net_price(int num) {
if (zekou > -0.00000001 && zekou < 0.00000001) {
return 1.1*num*0.8;
}else {
return 1.1*num*zekou;
}
}
main.cpp
#include "item_base.h"
#include "bulk_item.h"
#include <iostream>
using namespace std;
void print_total(item_base &item, int num) {
cout << item.book()
<< "\tnumber sold: "
<< num
<< "\ttotal price: "
<< item.net_price(num)
<< endl;
}
int main()
{
item_base ib;
cout << ib.book() << endl;
cout << ib.net_price(5) << endl;
print_total(ib, 5);
bulk_item bi(0.5);
cout << bi.net_price(5) << endl;
print_total(bi, 5);
}