流和几条设计准则

时间:2014.05.27

地点:基地

---------------------------------------------------------------------------------------

一、关于std::cin和std::cout

cin和cout的类型是std::istream和std::ostream 。这两个类型又分别对应着

std::basic_istream<char>
std::basic_ostream<char>

即,是分别是这二者typedef后的别名而已,当然,这里省略的模板的默认参数,完整来说是:

std::basic_istream<char,std::char_traits<char>>
std::basic_ostream<char,std::char_traits<char>>

---------------------------------------------------------------------------------------

二、流的rdbuf()成员函数

流的rdbuf()成员函数返回某个流对象说使用的streambbuf指针,该指针直接指向流底层使用的streambuf,正如前面一篇博文所说,绕过上层直接操作流的底层非常高效。另外,我的操作符operator<<()也接受这样一个指向streambuf的指针,于是对于某些操作,就像把一个池子的水端起来直接倒往另外一个水池一样,比起架起水管来让细水漫流是不是很爽?

---------------------------------------------------------------------------------------

三、应用

假设我们要写一个ECHO程序,简单的相应输入,能从cin获得输入,然后将输出发送到cout,也能从一个名为infile的文件获得输入,输往outfile文件。

有一条设计准则:

尽量提高可读性,避免撰写精简代码,避免晦涩。因为简洁代码难以理解和维护。

还有一条设计准则

尽量提高可扩充性

通过分析,我们知道,从获取输入到输出这个过程中,我们还可能要对数据进行一些处理,比如将字符进行大小写转换,删除一些字符,字符统计等,因此,我们需要将这一任务独立出来。

于是又有一条设计准则:

尽量提高封装性,将关系分离。

先来看整个程序框架:

int main(int argc, char* argv[])
{
	using namespace std;
	fstream in, out;
	if (argc > 1)
		in.open(argv[1], fstream::in, fstream::binary);
	if (argc > 2)
		out.open(argv[2], fstream::out | fstream::binary);
	Process(in.is_open()?in:cin,out.is_open()?out:cout);
	return EXIT_SUCCESS;
}

现在的问题是怎么去实现Process函数,我们将处理数据的任务交付给它,它应该能够处理不同的参数类型,我们想到的是多态,C++中有四种方式可获得多态行为:虚函数,模板,重载,转换。

3.1模板(编译时多态)

通过模板实现多态也叫编译时多态,提供有被传递对象的合适接口,实现如下:

template<typename In, typename Out>
void Process(In& in, Out& out)
{
       ....一些数据处理,
	//或者只是简单的这样:out << in.rdbuf();
}

3.2虚函数(运行时多态)

通过虚函数的方式的多态也叫运行时多态,它声明的参数类型是一个具有可能的接口们对应的公共基类即可。比如一种可能的实现如下:

void Process(basic_istream<char>& in,basic_ostream<char>& out)
{
  //...执行某些操作
  //或者只是这样 out<<in.rdbuf();  //把一池子水直接倒入另外一个池子
}

这种方式具有一定的依赖性,它要求输入和输出必须分别从basic_istream<char>和basic_ostream<char>派生。(我们的istream,ostream,iostream,ifstream,ofstream,stringstream等都分别从二者派生而来,可如果不是呢,比如宽字符流是基于wchar_t的。或者有些流有着用户自定义的traits。于是为了提高可扩充性,应该使用模板,让编译器去推导这些合适的参数

template<typename C,typename T>
void Process(basic_istream<C,T>& in,baise_ostream<C,T>& out)
{
       ......
}

但显然第一种方式比较看起来舒服。只要可能,一段代码一个函数或一个类,应该集中只知道和负责处理一件事。比如这里,程序包括两部分,一部分代码知道输入/输出源和目标中的可能区别,到底使用什么样的流,另一部分知道如何真正的执行处理。通过将这两部分分离,使得代码用途更加清晰,易于理解和阅读。

---------------------------------------------------------------------------------------

四、总结

避免写出来的代码只能解决当前问题,几乎任何时候若能写出可扩充的方案,都是更好的选择。但在编写专用代码只解决当前问题(短视,难以扩充)和编写一个宏大的通用框架去解决本来很简单的问题(追求过度设计)之间要自己琢磨取得最佳平衡。第一种方法简单而灵活,更能适应新要求,没有束缚,不仅仅只能和iostream体系打交道。在函数或类的设计中,我们应该尽量考虑可扩充性。稍微多去思考下,当前正在解决的问题是不是某个更通用问题的特例,于是应该还多做一点工作,而不要仅仅满足于当前。

流和几条设计准则

时间: 2024-08-29 13:23:48

流和几条设计准则的相关文章

全是干货!UI设计的30条黄金准则!

http://www.wex5.com/portfolio-items/js-1/ 全是干货!UI设计的30条黄金准则! 总的来说,好的UI界面有几个特征:简洁.便利.目标明确.人性化.字面上看这几点貌似很简单,但是考虑到我们的营销目标.考虑到内容复杂度,要确确实实达到这个目标却非常困难.下面列出的这些经验,一直以来在WeX5应用开发者社群中反复被验证,简单实用.极具操作性,WeX5开发工具强烈推荐给所有应用开发者及爱好者! 注:内容转化率是指用户浏览页面的时候能被用户吸收的内容比率. 1. 尝

类库开发的设计准则 读书笔记 1名称准则

MSDN链接:http://msdn.microsoft.com/zh-cn/library/vstudio/ms229042(v=vs.100).aspx 系列文章列表: 1名称准则:http://www.cnblogs.com/liu-meng/p/4181984.html 2类型设计准则:http://www.cnblogs.com/liu-meng/p/4182737.html 大小写的样式: Pascal 大小写 将标识符的首字母和后面连接的每个单词的首字母都大写. 可以对三字符或更多

雅虎36条优化准则

雅虎团队经验:网站页面性能优化的34条黄金守则1.尽量减少HTTP请求次数      终端用户响应的时间中,有80%用于下载各项内容.这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数.这是提高网页速度的关键步骤.      减少页面组件的方法其实就是简化页面设计.那么有没有一种方法既能保持页面内容的丰富性又能达到加快响应时间的目的呢?这里有几条减少HTTP请求次数同时又可能保持页面内容丰富的技术. 合并文件是通过把所有的脚本放到一个文件中

[译]类型设计准则

本文由 CYJB 译自 Type Design Guidelines(.NET Framework 4.5). 对 CLR 来说,只存在两种类型——引用类型和值类型.但是为了讨论框架设计,我们将类型细分为更多的逻辑组,每组有其特定的设计准则. 类是通用的引用类型,框架中的大部分类型都是类.类因其支持面向对象的大部分特性和普遍适应性而大受欢迎.基类和抽象类是与扩展性相关的特殊逻辑组. 接口是可以由引用类型和值类型实现的类型.它们可以作为引用类型和值类型的层次结构的根,或者模拟多重继承(CLR 本身

感想篇:12)像健康守则一样的机械设计准则

本章目的:尽可能多地去遵守机械设计准则. 1.可以违背的机械设计准则 机械设计准则不同于软件设计的准则. 软件设计,名字很软,但准则中非常多的是硬性的规定,特别是强语言,很多代码只要少一个分号就无法运行.(作者见过有个软件编程人员奋斗一下午就加了一个分号) 也就是说软件设计的准则不能违背,但就是这种严酷的规矩下,给了软件设计一个非常好的环境. 机械设计不一样,机械设计的名字很硬,但实际上,几乎所有的机械设计原则都是可以违反的.比如注塑件圆角,壁厚均匀等. 机械设计手册厚厚的六本,稍微入门一点的工

《c++编程剖析-问题,方案和设计准则》笔记

1vector的使用 我们只可以使用operator[]和at()去改动那些已经存在于容器中的东西. 而 用reserve()函数不会使得容器中充满函数,需要用resize()函数代替 当不对容器内的元素做任何改动时,记得使用const_iterator 2关于标准成员函数 C++标准库的实现中的成员函数签名并不要求与标准中说明的函数签名一模一样,它可以具有额外的默认函数. 这意味着,不同的标准库的成员函数签名可能不一致. 这也意味着,不存在一个可移植的指向标准库成员函数的指针. 同时也意味着不

数据库设计准则(第一、第二、第三范式说明)

数据库设计准则(第一.第二.第三范式说明) I.关系数据库设计范式介绍 1.1 第一范式(1NF)无重复的列 所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性.如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系.在第一范式(1NF)中表的每一行只包含一个实例的信息.简而言之,第一范式就是无重复的列. 说明:在任何一个关系数据库中,第一范式(1NF)是对

你没见过吧?16款形态各异的加载进度条设计

互联网连接越来越快,但难免有一些时刻需要我们等待.在这种情况下,创意的设计师尽力减轻用户等待的痛苦,苦思敏想设计各种创意的进度条(或加载条)效果 ,让用户等待的过程变得更加愉悦. 您可能感兴趣的相关文章 22套 Web & Mobile PSD 用户界面素材 45套精美的手机界面设计素材和设计工具 分享30套精美的Web和手机开发UI素材 60个精美的免费移动开发PSD素材资源 45套新鲜出炉的精美 PSD 网页设计素材 Loading by pearlsomani Flat Loading B

android抽屉导航的设计准则

我阅读了google官方的关于抽屉导航的设计准则,这可以给我带来什么帮助?最起码,我可以知道,抽屉导航适用在什么场景中,使用它时要注意什么事项.App的设计是有规则可以依据的,比如,使用抽屉导航时,是有明确的规则和场景的. The navigation drawer(导航抽屉) is a panel that transitions in from the left edge of the screen and displays the app’s main navigation options