C++模板類的複習記錄


翻出工程,整理總結下。供需要學習的看看就可以了。


# 函數模板


/**
 * 函數模板的定義形式:
 *
 * template <class T> 或 template <typename T>
 * 類型名 函數名(參數表)
 * {函數體的定義}
 */
template<typename T>
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);
}


# 類模板


/**
 * 類模板聲明的語法形式:
 *
 * 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()時會終止。
}


# 模板類不能分離編譯


/**
 * 注意:模板類不能分離編譯(除非實現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裏實現。


# 模板函數指針


/**
 * C++模板函數指針:http://www.cnblogs.com/easyfrog/archive/2012/11/04/2753468.html
 * 注意:struct封裝後的函數,再用在模板函數上不成。
 */
template<class T>
struct Wrapper {
    typedef void (*funcPtr)(T*, int);
};


或者,直接放到模板函數參數裏:


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;
}


# 附加產物


## 均勻隨機排列數組,以便測試排序算法


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_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:(一些基本變量)


CXXFLAGS = -O0 -g3 -Wall -c -fmessage-length=0
MD := mkdir -p
RM := rm -rf
OUT_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.init
SRCS := main.cpp
OBJS := $(OUT_DIR)/main.o
LIBS :=
TARGET := $(OUT_DIR)/temp_sort.exe
-include ../makefile.targets


記得把子目錄加進主makefile的DIRS裏就好了。


# 附件工程


其實就C++程序設計模板類那章內容罷了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章