翻出工程,整理总结下。供需要学习的看看就可以了。


# 函数模板


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
  * 函数模板的定义形式:
  *
  * template <class T> 或 template <typename T>
  * 类型名 函数名(参数表)
  * {函数体的定义}
  */
template < typename  T>
abs (T x)
{
     return  x < 0 ? -x : x;
}
template < class  T>
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);
}


# 类模板


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
  * 类模板声明的语法形式:
  *
  * template <模板参数列表>
  * class 类名
  * {类成员声明}
  *
  * 如果需要在类模板外定义其成员函数,则要采用以下的形式:
  *
  * template <模板参数列表>
  * 类型名 类名 <T> :: 函数名(参数表)
  *
  * “模板参数列表”由用逗号分隔的若干类型标识符或常量表达式构成,其内容包括:
  *
  * 1. class(或typename) 标识符,指明可以接受一个类型参数。
  * 2. 类型说明符 标识符,指明可以接受一个由“类型说明符”所规定类型的常量作为参数。
  *
  * 当“模板参数列表”同时包括上述多项内容时,各项内容以逗号分隔。
  * 应该注意的是,模板类的成员函数必须是模板函数。
  *
  * 使用一个模板类来建立对象时,应按如下形式声明:
  *
  * 模板<模板参数类表> 对象名1, ..., 对象名n;
  */
struct  Student {
     int  id;  // 学号
     float  gpa;  // 平均分
};
template < class  T>
class  Store {
public :
     Store( void );
     T GetElem( void );
     void  PutElem(T x);
private :
     T item;
     int  haveValue;
};
// 以下实现各成员函数
// 注意:模板类的成员函数,若在类外实现,则必须是模板函数
template < class  T>
Store<T>::Store( void )
     : haveValue(0)
{
}
template < class  T>
T Store<T>::GetElem( void )
{
     if  (haveValue == 0) {
         cout <<  "No item present!"  << endl;
         exit (1);  // 退出
     }
     return  item;
}
template < class  T>
void  Store<T>::PutElem(T x)
{
     haveValue++;
     item = x;
}
int  main()
{
     Student g = {1000, 23};
     Store< int > S1, S2;
     Store<Student> S3;
     Store< double > 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()时会终止。
}


# 模板类不能分离编译


1
2
3
4
/**
  * 注意:模板类不能分离编译(除非实现export的编译器)
  * @see <a href="http://stackoverflow.com/questions/10632251/undefined-reference-to-template-function">undefined reference</a>
  */


也就需要在头文件里实现。


我们可以在定义模板类的xxx.h末尾#include "xxx_impl.h",而后在xxx_impl.h里实现。


# 模板函数指针


1
2
3
4
5
6
7
8
/**
  * C++模板函数指针:http://www.cnblogs.com/easyfrog/archive/2012/11/04/2753468.html
  * 注意:struct封装后的函数,再用在模板函数上不成。
  */
template < class  T>
struct  Wrapper {
     typedef  void  (*funcPtr)(T*,  int );
};


或者,直接放到模板函数参数里:


1
2
3
4
5
6
7
8
9
template < class  T>
void  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;
}


# 附加产物


## 均匀随机排列数组,以便测试排序算法


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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是子目录,这里列全吧。以大概说明下工程里的内容。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
DIRS = \
     temp_func \
     temp_cls \
     temp_array \
     temp_list \
     temp_stack \
     temp_queue \
     temp_sort \
     temp_search
all:
     @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
clean:
     @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:(一些基本变量)


1
2
3
4
CXXFLAGS = -O0 -g3 -Wall -c -fmessage-length=0
MD := mkdir -p
RM := rm -rf
OUT_DIR := debug


makefile.targets:(通用的编译target)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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只需要这样:


1
2
3
4
5
6
-include ../makefile.init
SRCS := main.cpp
OBJS := $(OUT_DIR)/main.o
LIBS :=
TARGET := $(OUT_DIR)/temp_sort.exe
-include ../makefile.targets


记得把子目录加进主makefile的DIRS里就好了。


# 附件工程


其实就C++程序设计模板类那章内容罢了。