最近买了《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(, ); //OK:两个实参的类型都是int
max(, 4.2) //ERROR:第一个T是int,而第2个T是double

对于上面的错误,有三种方法可以解决:

1、对实参进行强制类型转换,使它们可以互相匹配:

max( static_cast<double>(), 4.2)   //OK

2、显式指定(或者限定)T的类型:

max<double>(, 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) < ? b : a;
} int main(int argc, char *argv[])
{
int a = ;
int b = ;
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();
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标记
}
}

关于《C++ Templates》的更多相关文章

  1. 关于<meta NAME="keywords" CONTENT="">

    昨天终于以实习身份入职一家小创业公司,今天让我多看看别人的网页怎么写的,发现了一个以前都没关注过的东西. <meta name="keywords" content=&quo ...

  2. 转 :meta name的含义:<META http-equiv=Content-Type content="text/html; charset=gb2312">

    meta是什么?meta其实是html语言head区的一个辅助性标签.在几乎所有的网页里,我们都可以看到类似下面这段html代码:<META http-equiv=Content-Type co ...

  3. HTML <meta> 标签 遇到<meta http-equiv="refresh" content="0; url=">详解

    页面定期刷新,如果加url的,则会重新定向到指定的网页,content后面跟的是时间(单位秒),把这句话加到指定网页的<head></head>里一般也用在实时性很强的应用中, ...

  4. 转 【<meta name="description" content=">】作用讲解

    今天在看别人写的网站代码,发现类似<meta name="Keywords" content="" >.<meta name="De ...

  5. <head>中<meta name="viewport" content="width=device-width,initical-scale=1"的作用>

    <meta name="viewport" content="width=device-width,initical-scale=1"的作用> co ...

  6. 关于<meta http-equiv="X-UA-Compatible" content="IE=edge" />问题

    我在做网页过程中都是在火狐浏览器下进行的,可是有一次我在IE浏览器下打开时却发现我设置的style.css中的大部分样式都失效率了,这个问题足足困扰了我两天,终于在百度的帮助下找到了答案,原来在网页的 ...

  7. 优先使用最新版本的IE 和 Chrome 内核 1 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

    兼容模式 优先使用最新版本的IE 和 Chrome 内核 1 <meta http-equiv="X-UA-Compatible" content="IE=edge ...

  8. 论meta name= viewport content= width=device-width initial-scale=1 minimum-scale=1 maximum-scale=1的作用

    一.先明白几个概念 phys.width: device-width: 一般我们所指的宽度width即为phys.width,而device-width又称为css-width. 其中我们可以获取ph ...

  9. meta name="viewport" content="width=device-width,initial-scale=1.0" 解释

     <meta name="viewport" content="width=device-width,initial-scale=1.0">   c ...

  10. <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 的说明

    X-UA-Compatible是针对ie8新加的一个设置,对于ie8之外的浏览器是不识别的,这个区别与 content="IE=7"在无论页面是否包含<!DOCTYPE> ...

随机推荐

  1. 使用tkinter做简单计算器

    代码如下: from tkinter import * #导入tkinter库 root =Tk() #给窗体 root.title('calculator') #设置窗体名字 frm=Frame(r ...

  2. Block的copy时机

    什么时候栈上的Block会复制到堆上呢? 1.调用Block的copy实例方法 2.Block作为函数返回值返回时 3.将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量 ...

  3. IOS方形头像如何变成圆形

    方法一:直接使用UIView对应图层的cornerRadius self.layer.cornerRadius     = CGRectGetWidth(self.bounds)/2.f; self. ...

  4. ASP.NET根据IP获取省市地址

    1.在网站的跟路径下面添加 QQWry.dat 文件,这个文件是IP数据库文件 2.添加以下一个类 IPScanner     C# 代码   复制 public class IPScanner { ...

  5. c++刷题(27/100)反转单项链表,链表的倒数第k个

    题目1:调整数组顺序使奇数位于偶数前面 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位 ...

  6. 【leetcode 简单】 第七十一题 二叉树的所有路径

    给定一个二叉树,返回所有从根节点到叶子节点的路径. 说明: 叶子节点是指没有子节点的节点. 示例: 输入: 1 / \ 2 3 \ 5 输出: ["1->2->5", ...

  7. 文件读取 FILE

    需要了解的概念 [数据流][缓冲区(Buffer)][文件类型][文件存取方式][借助文件指针读写文件] 需要理解的知识点包括:数据流.缓冲区.文件类型.文件存取方式 1.1 数据流: 指程序与数据的 ...

  8. js数组排序 reverse()和sort()方法的使用

    WEB前端|js数组排序reverse()和sort()方法的使用,数组中已经存在两个可以直接用来重排序的方法:reverse()和sort(). reverse()方法会对反转数组项的顺序. var ...

  9. zookeeper集群查看状态时报错Error contacting service. It is probably not running的一些坑以及解决办法

    最近在搭建mq集群时候需要用到,zookeeper,可是启动的时候显示成功了,查看状态的时候却报错了: 碰到这个问题也是研究好好半天才解决,这里就总结出一个快速解决办法! 首先,必须看日志: 报错信息 ...

  10. 【FCS NOI2018】福建省冬摸鱼笔记 day5

    第五天,也是讲课的最后一天. 数据结构专题,讲师:杨志灿 他的blog我似乎找不到了……以前肯定是在百度博客里面.但是现在百度博客消失了. PPT做的很有感觉,说了很多实用的技巧. 我觉得其实是收获最 ...