关于C/C++的一些思考(5)
运算符重载函数的限制:
五个不能实现重载的符号:".", ".*", "::", "?", "sizeof";
重载运算符可以定义为类成员函数(这时候可以向当前对象发送消息的动作执行操作),也可定义为全局函数(一般为对应类的友元函数,此类函数需要显式指定所有参数,并且如果有转换构造函数,则可以使用于所有参数类型的运算);
一般的重载运算符函数可以被派生类继承使用,但是赋值运算符重载函数不能被继承;因此每一个派生类都最好定义自己的赋值运算符重载函数;
重载运算符函数需要与运算符本身的属性保持一致:优先级,结核性,参数个数等;
转换构造函数一般使用于隐式调用,用于将一般类型转换为当前类的类型,而转换运算符函数一般适用于显式转换,用于将当前类型转换为其他类型(注意这个函数没有返回值,但是需要使用return返回对应的类型数据,并且不能有任何参数)
输入输出运算符的重载一般形式为:(实现为全局函数,并且支持链式操作)
public : friend istream& operator >> (istream& in, String &s);
public : friend ostream& operator << (ostream& out, String &s);
为了让程序适用于多种不同类型:
可以将关键变量的类型使用typedef定义为一个内部变量,但是不支持多种类型同时使用同一算法容器的情况,也就是每改变一次参数类型,程序都需要重新编译:
typedef char Type;
class Stack {Type *items; ……};
还可以使用#define宏定义将整个程序代码创建成宏定义,由于宏定义中的参数不会进行类型检查,所以可以将关键字类型定义为参数的内部变量。由于宏定义语句中基本不能进行调试,所以这不能大规模使用;
模板类(template class),将元素的类型作为类的可选参数,可以用同一算法容器支持所有具有所需操作的类型的变量的处理
定义模板类:(类方法的实现体之前需要声明模板类型标记)
template <class Type>
class Stack {
Type *items;
……
~Stack();
void push(const Type&);
};
template <class Type>
Stack<Type>::~Sack();
template <class Type>
void Stack<Type>::push(const Type&){……}实例化具体类:
Stack<char> charString(20);
charString.push('i');
模板类定义和实例化的限制:
模版类中定义的类别名需要在对象实例化过程中使用实际的类型替换,但要求这种类型支持类定义中的所有操作,否则会在编译时期报错;因此在编译阶段到达模板类实例化具体类的时候,就会针对实际传入的类类型进行语法查错,如果传入类型支持所有的操作则正确生成对应的代码;
形如:template <class T1, class T2, int size>中T1和T2是定义的类型,实例化中需要使用具体的类型名初始化,size则是一个数值,实例化的时候需要使用具体的数值进行初始化,并 且这个初始化值不能是运行期变量,需要const变量或者是数值常量(编译期间就能确定的值)
将某个模板类申明为友元类
template <class T>
class Stack {};
class Node {template <class T> friend class Stack};
或者
template <class Type>
class Node {friend class Stack<Type>;};
如果一个模板类声明了静态数据成员,那么每一个模板的实例都将独立拥有一份静态数据成员的内存数据;也就是说模板实例化将重新创建一份独立的类代码,相同 模板的不同实例之间不会共享任何内存;对于模板类的静态成员而言,其也会进行缺省初始化,但其不同于一般的静态数据成员会在程序开始之前进行,而是在具体 实例化一个模板对象(也就是指定类参数)的时候进行:
template <class T>
class Stack {
static Stack *top;
};模板静态成员的初始化:
template <class T>
Stack<T>* Stack<T>::top=NULL;
模版机制是在编译时期而不是运行时期进行数据类型检查,所以更加安全,并且可用于基本类型,不像多态技术只能用于类的成员函数,同时其绑定时期也在编译阶段,所以运行效率更高:模版机制是在编译时期而不是运行时期进行数据类型检查,所以更加安全,并且可用于基本类型,不像多态技术只能用于类的成员函数,同时其绑定时期也在编译阶段,所以运行效率更高:
- 模版的优势:
可用来创建动态增长和减小的数据结构;
它是类型无关的,因此具有很高的可复用性;
它在编译时而不是运行时检查数据类型是否与操作匹配,保证了类型安全;
它是平台无关的,可移植性;
可用于基本数据类型;
模版用途:同样的逻辑表示,只是因为不同的参数或者返回值类型而不同公用同一套逻辑,这时候需要将类型转变成可替换的;
宏定义虽然也可以实现为多种类型提供一套逻辑实现,但是它避开了类型检查,使得程序调试难以实现,并且由于是文本替换,所以容易出现副作用;
模版是实现代码复用的一种工具,可以实现类型参数化,将类型定义为参数,在编译时候进行类型检查(查看用户传入类型是否支持该类型所有的操作);
函数模板的实例化是由编译程序在处理函数调用时自动完成的(静态绑定),而类模板的实例化必须由程序员在程序中显式地指定;
模版分成两类,函数模版:
声明格式为:
Template <typename [类型参数标示]> [返回类型] [函数名](参数列表)其中的typename也可以替换为class,并且template和函数头之间不能再有其他语句;
支持多个类型的参数化,但是每个类型参数之前需要添加typename或者class;
允许通过不同的参数类型而进行重载,但是仅仅支持全特化;
- 模版分成两类,类模版:
声明格式:
Template <typename [类型参数标示]> Class [类名]{类定义}类成员函数实现时,所有方法前都需要添加template <typename [类型参数标示]>,可以进行全特化和偏特化;
特化机制是建立在一般模板类定义(模板函数同样适用)的基础上的,对其中的某一个或者某几个类型参数进行特化定义的机制;编译器进行选择时首先从特化程度 最大的模板定义中选择合适的定义,最后才考虑一般模板定义。STL模版特化(Template Specialization)和偏特化(Template Partial Specialization):
- 模板特化:指定一个或者多个模板形参的实际类型或者实际值,如下所示第一个函数Compare是一般的模板实现,第二个Compare函数就是第一个模板函数的特化,所以编译中如果形参类型是const char*, const char* 则调用第二个特化函数:
template <typename T>
int Compare(const T &x, const T &y)
{
if(x < y)
return -;
else if(x > y)
return ;
else
return ;
}
template <> //template关键字后面接空括号
int Compare(const char * const &x, const char * const &y) //形参为指向常量的常指针的引用
{
return strcmp(x, y);
}参考链接:
http://blog.csdn.net/wuzhekai1985/article/details/6654667 - 模板的偏特化:需要根据模板的某些但不是全部参数进行特化:
//
template <class T>
class Array {T *data;};
//
template <>
class Array <char *> {char* data;};//
template <class T>
class Array {T *data;};
//
template <>
class Array <char *> {char* data;};这样当使用Array<int> a;的时候编译器自动匹配一般的模板,当使用Array<char*> a的时候则编译器匹配第二个特殊化的模板,这样就可以针对具体的类型实现不同的类实现;函数的特化与类的特化类似;
当模板参数有多个的时候,编译器支持部分参数的特化:
//
template <class Key, class Data>
class Item {Key key; Data data;};
//
template <class Data>
class Item <char *> {char *key, Data data};
//
template <>
class Item <char *, char *> {char *key, char *data};
//
template <class key>
class Item <key, char *> {Key key, char *data};特化参数需要遵循从左向右的顺序,可以偏特化,也可以全特化;实际调用中会根据匹配程度最大的模板生成对应的代码;当然也可以仅特化第二个参数,但是需要在类定义中添加第一个类型参数的占位符;
为什么需要Type-Traits:
对于不同类型执行相同的操作,希望有一个公用的接口,然后根据具体的类型实现不同的调用;
基于虚函数实现的多态机制只能针对类定义对象,对于语言内置类型,指针类型并不适用;
多态机制是动态绑定,在某种程度上比编译时期绑定更加耗时,type-traits可以在编译时期进行绑定;
关于C/C++的一些思考(5)的更多相关文章
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
- 关于面试题 Array.indexof() 方法的实现及思考
这是我在面试大公司时碰到的一个笔试题,当时自己云里雾里的胡写了一番,回头也曾思考过,最终没实现也就不了了之了. 昨天看到有网友说面试中也碰到过这个问题,我就重新思考了这个问题的实现方法. 对于想进大公 ...
- 关于 CSS 反射倒影的研究思考
原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...
- 关于.NET参数传递方式的思考
年关将近,整个人已经没有了工作和写作的激情,估计这个时候很多人跟我差不多,该相亲的相亲,该聚会喝酒的聚会喝酒,总之就是没有了干活的心思(我有很多想法,但就是叫不动我的手脚,所以我只能看着别人在做我想做 ...
- 使用NUnit为游戏项目编写高质量单元测试的思考
0x00 单元测试Pro & Con 最近尝试在我参与的游戏项目中引入TDD(测试驱动开发)的开发模式,因此单元测试便变得十分必要.这篇博客就来聊一聊这段时间的感悟和想法.由于游戏开发和传统软 ...
- OpenGL shader 中关于顶点坐标值的思考
今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...
- 关于领域驱动设计(DDD)中聚合设计的一些思考
关于DDD的理论知识总结,可参考这篇文章. DDD社区官网上一篇关于聚合设计的几个原则的简单讨论: 文章地址:http://dddcommunity.org/library/vernon_2011/, ...
- 关于bug分析与异常处理的一些思考
前言:工作三年了,工作内容主要是嵌入式软件开发和维护,用的语言是C,毕业后先在一家工业自动化控制公司工作两年半,目前在一家医疗仪器公司担任嵌入式软件开发工作.软件开发中,难免不产生bug:产品交付客户 ...
- 【数据库】_由2000W多条开房数据引发的思考、实践----给在校生的一个真实【练耙场】,同学们,来开始一次伟大的尝试吧。
× 缘起---闲逛博客园 前几天的时候,在某一QQ群看到一条消息“XXX酒店开房XXXBTXX迅雷BT下载”,当时是一目十行的心态浏览,目光掠过时, 第一反应我想多了~以为是XX种子(你懂的~ ...
- 对于多个数据库表对应一个Model问题的思考
最近做项目遇到一个场景,就是客户要求为其下属的每一个分支机构建一个表存储相关数据,而这些表的结构都是一样的,只是分属于不同的机构.这个问题抽象一下就是多个数据库表对应一个Model(或者叫实体类).有 ...
随机推荐
- PTA 螺旋方阵
所谓"螺旋方阵",是指对任意给定的NNN,将1到N×NN\times NN×N的数字从左上角第1个格子开始,按顺时针螺旋方向顺序填入N×NN\times NN×N的方阵里.本题要求 ...
- U3D 的一些基础优化
1.在使用数组或ArrayList对象时应当注意 [csharp] view plaincopy length=myArray.Length; for(int i=0;i<length;i++) ...
- 3DMAX 8 角色建模2 身体
身体 20 25 60 分段 3 2 3 位置直接设置到-12.5 0 0,删除内部面,实例镜像出另一半x偏移25 1 身体大体形状 ,,,, 2 背阔肌 , 3腹肌 4 臀部 ,, 5 肩部 调整点 ...
- 如何阻止浏览器的默认事件,你是否也遇到过无法阻止Google默认事件的情况( 原生JS )
如题,话不多话,我们先看怎么解决 根据不同的绑定事件的方法,我们有不同的阻止默认事件的方法 如果你不知到如何绑定事件,请查看我的上一篇文章 关于浏览器滚动的兼容性问题以及事件绑定 1.句柄绑定 只需要 ...
- (构造)51NOD 1080 两个数的平方和
给出一个整数N,将N表示为2个整数i与j的平方之和(i <= j),如果有多种表示,按照i的递增序输出. 例如:N = 130,130 = 3^2 + 11^2 = 7^2 + 9^2(注:3^ ...
- Selenium | 网上教程
java selenium (一) selenium 介绍 java selenium (二) 环境搭建方法一 java selenium (三) 环境搭建 基于Maven java selenium ...
- The 17th Zhejiang University Programming Contest Sponsored by TuSimple A
Marjar Cola Time Limit: 1 Second Memory Limit: 65536 KB Marjar Cola is on sale now! In order to ...
- DataGridView 绑定List<>数据的更新
使用BindingSource做为中间数据源,使用 bindingSource1.DataSource = productOrderList;dataGridView1.DataSource = bi ...
- P1720 月落乌啼算钱
题目背景 (本道题目木有以藏歌曲……不用猜了……) <爱与愁的故事第一弹·heartache>最终章. 吃完pizza,月落乌啼知道超出自己的预算了.为了不在爱与愁大神面前献丑,只好还是硬 ...
- Springboot 1.X 在Weblogic 中的发布
springboot在tomcat中的兼容性很好,但是如果要把Springboot项目发布在weblogic,尤其是老版本的Weblogic就会出现各种问题.经过本人的不懈努力及查询资料,终于将Spr ...