最近买了《C++ Templates》来看,书最开始部分阐述了关于此书的一些编程风格。本人感觉非常好,有些地方之前一直容易搞混,这里却讲述的很清楚。例如:
关于下面几种风格的代码:
void foo(const int &x); void foo(const int& x); void foo(int const &x); void foo(int const& x);
对于上面四种用法,差别虽然不是很大,但是我们更倾向于使用int const,而不是const int。
主要原因:1、关于“恒定不变部分”指的是const限定符前面的部分。
记住这句话,相信诸如此类:int* const book_mark; 和 int const* book_mark; const int* book_mark; 的含义就不会搞错了。
2、使用模板时一个很常用的语法替换原则。例如:
typedef char* CHARS; typedef CHARS const CPTR; //指向char类型的常量指针,即指针不能改变
当我们用CHARS进行替换后,第2个声明的含义是不变的:
typedef char* const CPTR;
然而,如果我们把const放在它所限定的类型的前面,那么这个原则就不再适用了。考虑如下:
typedef char* CHARS; typedef const CHARS CPTR; //指向char类型的常量指针,即指针不能改变
如果我们替换CHARS后,第2个声明将导致不同的含义:
typedef const char* CPTR; //指向常量char类型的指针
另外,对于本书的的前两章,下面列了几点重要的结论:
- 模板在编译期间被编译了两次,分别发生在:
1、实例化之前,先检查模板代码之前,查看语法是否正确;在这里会发现错误的语法,如遗漏分号等。
2、在实例化期间,检查模板代码,查看时候所有的调用都有效。在这里会发现无效的调用,如该实例化类型不支持某些函数的调用等。
- 实参演绎时,不允许进行自动类型转换;每个T都必须正确地匹配。如:
template<typename T> inline T const& max(T const& a, T const& b); max(4, 7); //OK:两个实参的类型都是int max(4, 4.2) //ERROR:第一个T是int,而第2个T是double
对于上面的错误,有三种方法可以解决:
1、对实参进行强制类型转换,使它们可以互相匹配:
max( static_cast<double>(4), 4.2) //OK
2、显式指定(或者限定)T的类型:
max<double>(4, 4.2) //OK
3、指定两个参数可以具有不同的类型。
下面从书中摘取了两个例子,代码比较简单,如下所示:
1、函数模板重载的例子。
/********************************************************** * @filename: C++ templates example: function overloading * @author: JackyLiu * @data: 2013.6.25 ***********************************************************/ #include <iostream> #include <cstring> #include <string> //求两个任意类型值的最大值///////////////////////////// template <typename T> inline T const& max(T const& a, T const& b) { return a < b ? b : a; } //求两个指针所指向值的最大值/////////////////////////// template<typename T> inline T const& max(T* const& a, T* const& b) { return *a < *b ? *b : *a; } //求两个C字符串的最大者//////////////////////////////// inline char const* const& max(char const* const& a, char const* const& b) { return std::strcmp(a,b) < 0 ? b : a; } int main(int argc, char *argv[]) { int a = 7; int b = 42; std::cout<< ::max(a, b)<< std::endl; //max()求两个int值的最大值 std::string s = "hey"; std::string t = "you"; std::cout<< ::max(s,t)<< std::endl; //max()求两个std::string类型的最大值 int *p1 = &b; int *p2 = &a; std::cout<< ::max(p1,p2)<< std::endl; //max()求两个指针所指向值得最大者 char const* s1 = "David"; char const* s2 = "Nico"; std::cout<< ::max(s1, s2)<< std::endl; //max()求两个c字符串的最大值 int i; std::cin>> i; }
2、类模板的例子:
stack3.hpp
#include <vector> #include <stdexcept> /** * 缺省模板实参 */ template<typename T, typename CONT = std::vector<T> > class Stack { private: CONT elems; public: void push(T const&); void pop(); T top() const; bool empty() const { return elems.empty(); } }; template<typename T, typename CONT> void Stack<T, CONT>::push(T const& elem) { elems.push_back(elem); } template<typename T, typename CONT> void Stack<T, CONT>::pop() { if(elems.empty()) throw std::out_of_range("Stack<>::pop(): empty stack"); elems.pop_back(); } template<typename T, typename CONT> T Stack<T, CONT>::top() const { if(elems.empty()) throw std::out_of_range("Stack<>::pop(): empty stack"); return elems.back(); }
main.cpp
/******************************************************************* * @filename: the implementation of the class template of stack * @author: JackyLiu * @date: 2013.6.25 ********************************************************************/ #include <iostream> #include <deque> #include <string> #include <cstdlib> //#include "stack1.hpp" #include "stack3.hpp" int main(int argc, char *argv[]) { /********************************************************************* try { Stack<int> intStack; //元素类型为int的栈 Stack<std::string> stringStack; //元素类型为字符串的栈 //使用int栈 intStack.push(7); std::cout << intStack.top() << std::endl; //使用string栈 stringStack.push("hello"); std::cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch(std::exception const& ex) { std::cerr << "Exception: " << ex.what() << std::endl; int i; std::cin >> i; return EXIT_FAILURE; //程序退出,且带有ERROR标记 } */ try { //int栈 Stack<int> intStack; //double栈,它使用std::deque来管理元素 Stack<double, std::deque<double> > dblStack; //使用int栈 intStack.push(7); std::cout << intStack.top() << std::endl; intStack.pop(); //使用double栈 dblStack.push(42.42); std::cout << dblStack.top() << std::endl; dblStack.pop(); dblStack.pop(); } catch(std::exception const& ex) { std::cerr << "Exception: " << ex.what() << std::endl; int i; std::cin >> i; return EXIT_FAILURE; //退出程序,且有ERROR标记 } }