翻出工程,整理总结下。供需要学习的看看就可以了。
# 函数模板
/** * 函数模板的定义形式: * * template或 template * 类型名 函数名(参数表) * {函数体的定义} */template T abs(T x){ return x < 0 ? -x : x;}template void outputArray(const T *P_array, const int count){ for (int i = 0; i < count; i++) cout << P_array[i] << " "; cout << endl;}int main(){ int n = -5; double d = -5.5; cout << abs(n) << endl; cout << abs(d) << endl; const int aCount = 8, bCount = 8, cCount = 20; int aArray[aCount] = {1, 2, 3, 4, 5, 6, 7, 8}; double bArray[bCount] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8}; char cArray[cCount] = "Welcome to see you!"; cout << "a Array contains:" << endl; outputArray(aArray, aCount); cout << "b Array contains:" << endl; outputArray(bArray, bCount); cout << "c Array contains:" << endl; outputArray(cArray, cCount);}
# 类模板
/** * 类模板声明的语法形式: * * template <模板参数列表> * class 类名 * {类成员声明} * * 如果需要在类模板外定义其成员函数,则要采用以下的形式: * * template <模板参数列表> * 类型名 类名:: 函数名(参数表) * * “模板参数列表”由用逗号分隔的若干类型标识符或常量表达式构成,其内容包括: * * 1. class(或typename) 标识符,指明可以接受一个类型参数。 * 2. 类型说明符 标识符,指明可以接受一个由“类型说明符”所规定类型的常量作为参数。 * * 当“模板参数列表”同时包括上述多项内容时,各项内容以逗号分隔。 * 应该注意的是,模板类的成员函数必须是模板函数。 * * 使用一个模板类来建立对象时,应按如下形式声明: * * 模板 <模板参数类表> 对象名1, ..., 对象名n; */struct Student { int id; // 学号 float gpa; // 平均分};template 模板参数列表> 模板参数列表>class Store {public: Store(void); T GetElem(void); void PutElem(T x);private: T item; int haveValue;};// 以下实现各成员函数// 注意:模板类的成员函数,若在类外实现,则必须是模板函数template 模板参数类表>Store ::Store(void) : haveValue(0){}template T Store ::GetElem(void){ if (haveValue == 0) { cout << "No item present!" << endl; exit(1); // 退出 } return item;}template void Store ::PutElem(T x){ haveValue++; item = x;}int main(){ Student g = {1000, 23}; Store S1, S2; Store S3; Store D; S1.PutElem(3); S2.PutElem(-7); cout << S1.GetElem() << " " << S2.GetElem() << endl; S3.PutElem(g); cout << "The student is " << S3.GetElem().id << endl; cout << "Retrieving object D "; cout << D.GetElem() << endl; // D未设值,D.GetElem()时会终止。}
# 模板类不能分离编译
/** * 注意:模板类不能分离编译(除非实现export的编译器) * @see undefined reference */
也就需要在头文件里实现。
我们可以在定义模板类的xxx.h末尾#include "xxx_impl.h",而后在xxx_impl.h里实现。
# 模板函数指针
/** * C++模板函数指针:http://www.cnblogs.com/easyfrog/archive/2012/11/04/2753468.html * 注意:struct封装后的函数,再用在模板函数上不成。 */templatestruct Wrapper { typedef void (*funcPtr)(T*, int);};
或者,直接放到模板函数参数里:
templatevoid timeit(void (*funcPtr)(T*, int), T A[], int n) { clock_t stamp_start, stamp_end; stamp_start = clock(); funcPtr(A, n); // 执行函数 stamp_end = clock(); double duration = (double) (stamp_end - stamp_start) / CLOCKS_PER_SEC; cout << "Cost: " << duration << " secs." << endl;}
# 附加产物
## 均匀随机排列数组,以便测试排序算法
void swap(int *a, int *b){ int t; t = *a; *a = *b; *b = t;}// 均匀随机排列[0,n-1]int* rand_ints(const int n){ srand((unsigned) time(0)); // 随机种子 int *a = new int[n]; int i; for (i = 0; i < n; ++i) { a[i] = i; } for (i = n; i > 1; --i) { // swap A[i-1] & A[RANDOM(0, i-1)] swap(&a[i - 1], &a[rand() % i]); } return a;}
## 多工程目录的makefie配置方法
makefile:(主makefile)
DIRS是子目录,这里列全吧。以大概说明下工程里的内容。
DIRS = \ temp_func \ temp_cls \ temp_array \ temp_list \ temp_stack \ temp_queue \ temp_sort \ temp_searchall: @for dir in $(DIRS) ; do \ if test -d $$dir ; then \ echo "$$dir: $(MAKE) $@" ; \ if (cd $$dir; $(MAKE) $@) ; then \ true; \ else \ exit 1; \ fi; \ fi \ doneclean: @for dir in $(DIRS) ; do \ if test -d $$dir ; then \ echo "$$dir: $(MAKE) $@" ; \ if (cd $$dir; $(MAKE) $@) ; then \ true; \ else \ exit 1; \ fi; \ fi \ done
然后准备一个头一个尾:
makefile.init:(一些基本变量)
CXXFLAGS = -O0 -g3 -Wall -c -fmessage-length=0MD := mkdir -pRM := rm -rfOUT_DIR := debug
makefile.targets:(通用的编译target)
all: $(TARGET)$(TARGET): $(OBJS) @echo ' ' @echo 'Building target: $@' $(CXX) -o "$(TARGET)" $(OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' '$(OUT_DIR)/%.o: %.cpp @echo ' ' @echo 'Building file: $<' $(MD) $(OUT_DIR) $(CXX) $(CXXFLAGS) -o "$@" "$<" @echo 'Finished building: $<'clean: $(RM) $(OBJS) $(TARGET)
继而,子目录下makefile只需要这样:
-include ../makefile.initSRCS := main.cppOBJS := $(OUT_DIR)/main.oLIBS :=TARGET := $(OUT_DIR)/temp_sort.exe-include ../makefile.targets
记得把子目录加进主makefile的DIRS里就好了。
# 附件工程
其实就C++程序设计模板类那章内容罢了。