C/C++知识点总结(5)

运算符重载函数的限制:

  • 五个不能实现重载的符号:".", ".*", "::", "?", "sizeof";

  • 重载运算符可以定义为类成员函数(这时候可以向当前对象发送消息的动作执行操作),也可定义为全局函数(一般为对应类的友元函数,此类函数需要显式指定所有参数,并且如果有转换构造函数,则可以使用于所有参数类型的运算);

  • 一般的重载运算符函数可以被派生类继承使用,但是赋值运算符重载函数不能被继承;因此每一个派生类都最好定义自己的赋值运算符重载函数;

  • 重载运算符函数需要与运算符本身的属性保持一致:优先级,结核性,参数个数等;

转换构造函数一般使用于隐式调用,用于将一般类型转换为当前类的类型,而转换运算符函数一般适用于显式转换,用于将当前类型转换为其他类型(注意这个函数没有返回值,但是需要使用return返回对应的类型数据,并且不能有任何参数)

输入输出运算符的重载一般形式为:(实现为全局函数,并且支持链式操作)

1 public : friend istream& operator >> (istream& in, String &s);
2 public : friend ostream& operator << (ostream& out, String &s);

为了让程序适用于多种不同类型:

  • 可以将关键变量的类型使用typedef定义为一个内部变量,但是不支持多种类型同时使用同一算法容器的情况,也就是每改变一次参数类型,程序都需要重新编译:

    typedef char Type;

    class Stack {Type *items; ……};


  • 还可以使用#define宏定义将整个程序代码创建成宏定义,由于宏定义中的参数不会进行类型检查,所以可以将关键字类型定义为参数的内部变量。由于宏定义语句中基本不能进行调试,所以这不能大规模使用;

  • 模板类(template class),将元素的类型作为类的可选参数,可以用同一算法容器支持所有具有所需操作的类型的变量的处理

    定义模板类:(类方法的实现体之前需要声明模板类型标记)


     1 template <class Type>
    2 class Stack {
    3 Type *items;
    4 ……
    5 ~Stack();
    6 void push(const Type&);
    7 };
    8 template <class Type>
    9 Stack<Type>::~Sack();
    10 template <class Type>
    11 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* 则调用第二个特化函数:


     1 template <typename T>
    2 int Compare(const T &x, const T &y)
    3 {
    4 if(x < y)
    5 return -1;
    6 else if(x > y)
    7 return 1;
    8 else
    9 return 0;
    10 }
    11 template <> //template关键字后面接空括号
    12 int Compare(const char * const &x, const char * const &y) //形参为指向常量的常指针的引用
    13 {
    14 return strcmp(x, y);
    15 }

    参考链接:
    http://blog.csdn.net/wuzhekai1985/article/details/6654667


  • 模板的偏特化:需要根据模板的某些但不是全部参数进行特化:


     1 //1
    2 template <class T>
    3 class Array {T *data;};
    4 //2
    5 template <>
    6 class Array <char *> {char* data;};//1
    7 template <class T>
    8 class Array {T *data;};
    9 //2
    10 template <>
    11 class Array <char *> {char* data;};

    这样当使用Array<int> a;的时候编译器自动匹配一般的模板,当使用Array<char*>
    a的时候则编译器匹配第二个特殊化的模板,这样就可以针对具体的类型实现不同的类实现;函数的特化与类的特化类似;

    当模板参数有多个的时候,编译器支持部分参数的特化:


     1 //1
    2 template <class Key, class Data>
    3 class Item {Key key; Data data;};
    4 //2
    5 template <class Data>
    6 class Item <char *> {char *key, Data data};
    7 //3
    8 template <>
    9 class Item <char *, char *> {char *key, char *data};
    10 //4
    11 template <class key>
    12 class Item <key, char *> {Key key, char *data};

    特化参数需要遵循从左向右的顺序,可以偏特化,也可以全特化;实际调用中会根据匹配程度最大的模板生成对应的代码;当然也可以仅特化第二个参数,但是需要在类定义中添加第一个类型参数的占位符;

为什么需要Type-Traits:

  • 对于不同类型执行相同的操作,希望有一个公用的接口,然后根据具体的类型实现不同的调用;

  • 基于虚函数实现的多态机制只能针对类定义对象,对于语言内置类型,指针类型并不适用;

  • 多态机制是动态绑定,在某种程度上比编译时期绑定更加耗时,type-traits可以在编译时期进行绑定;

C/C++知识点总结(5),布布扣,bubuko.com

时间: 2024-10-13 01:53:45

C/C++知识点总结(5)的相关文章

H5移动端知识点总结

移动开发基本知识点 一. 使用rem作为单位html { font-size: 100px; }@media(min-width: 320px) { html { font-size: 100px; } }@media(min-width: 360px) { html { font-size: 112.5px; } }@media(min-width: 400px) { html { font-size: 125px; } }@media(min-width: 640px) { html { f

Spring知识点回顾(01)

Spring知识点回顾(01) 一.依赖注入 1.声明Bean的注解 @Component @Service @Repository @Controller 2.注入Bean的注解 @Autowired @Inject @Resource 二.加载Bean 1.xml方式 - applicationcontext.xml : Beans, Bean, Component-Scan 2.注解方式 - @Configuration,@ComponentScan,@Bean 用@Configurati

Javascript易错知识点

? JS易错知识点总结: == 和 === 的区别: ==:判断两个变量的值是否相等. ===:判断两个变量的类型和值是否都相等,两个条件同时满足时,表达式为True. switch中break的作用: 如果一个case后面的语句,没有写break,那么程序会向下执行,而不会退出: 例如:当满足条件的case 2下面没有break时,case 3也会执行 1 var num = 2; 2 switch(num){ 3 case 1: 4 alert('case 1'); 5 break; 6 c

老男孩教育每日一题-2017年5月11-基础知识点: linux系统中监听端口概念是什么?

1.题目 老男孩教育每日一题-2017年5月11-基础知识点:linux系统中监听端口概念是什么? 2.参考答案 监听端口的概念涉及到网络概念与TCP状态集转化概念,可能比较复杂不便理解,可以按照下图简单进行理解? 将整个服务器操作系统比喻作为一个别墅 服务器上的每一个网卡比作是别墅中每间房间 服务器网卡上配置的IP地址比喻作为房间中每个人 而房间里面人的耳朵就好比是监听的端口 当默认采用监听0.0.0.0地址时,表示房间中的每个人都竖起耳朵等待别墅外面的人呼唤当别墅外面的用户向房间1的人呼喊时

JavaScript一些重要知识点结合题目的表现!

function Foo() { //① 声明一个Foo的函数 getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2);}; ② 为Foo创建一个叫getName的静态属性存储一个匿名函数 Foo.prototype.getName = function () { alert (3);}; ③为Foo的原型对象创建一个叫getName的匿名函数 var getName =

学完了js的知识,一起分享总结知识点

又一个知识点学完了,到了总结学习效果和知识总结的时间了.js这个编程语言相对于html和css的逻辑性要强一些,也比较不容易上手.概念性的知识点不难理解,就是实际的操作并不容易,需要通过学习和借鉴案列来理解和帮助并提高实践操作的能力,把理论知识更好的结合到实践当中去,这样才能更有利于去理解和提高自己,做到知识的真正转化,缺乏理论概念性的支撑,有时真的很难上手,尤其是对于刚学习新手而言.所以需要总结知识点,大家可以互相分享一下学习的方式方法,知识总结,通过这种方式方法,相信可以有效的帮助解决一些学

C#高级知识点概要(1) - 委托和事件

作者:linybo 要成为大牛,必然要有扎实的基本功,不然时间再长项目再多也很难有大的提升.本系列讲的C# 高级知识点,是非常值得去撑握的,不仅可以让你写代码时游刃有余,而且去研究和学习一些开源项目时,也不会显得那么吃力了. 希望大家记住,这里讲的所有的知识点,不仅仅是了解了就可以了,还要会灵活用,一定要多思考,撑握其中的编程思想. 本文讲的是委托和事件,这两个词可能你早就耳熟能详,但你是否真正撑握了呢? 本系列讲的C#高级知识点都是要求开发时能达到可以徒手写出来的水平(不依赖搜索引擎.找笔记等

关于Less,你必知的知识点

这是一篇关于Less学习教程 http://www.maiziedu.com/course/497/,讲解了Less的语法,Less的混合等知识点. 1. 关于 less sass 的预编译处理器 LESS 将 CSS 赋予了动态语言的特性,如 变量, 继承, 运算, 函数. LESS 既可以在 客户端 上运行 (支持IE 6+, Webkit, Firefox),也可以借助Node.js或者Rhino在服务端运行. less 编译使用前期使用koala 编译 2. less的 语法 A): 注

JavaScript 总结几个提高性能知识点

前段时间花时间看了大半的<High Performance JavaScript>这本书啊,然后就开始忙项目了,庆幸最忙的一周已经熬过去了.由于空不出时间,这个月写的学习笔记也不多,忙完最苦X的一周,这两天晚上也算是挑灯夜读了...终于是在残血之际将这本书shut down了... 既然读完了,总归是要学到些什么的.说说对这本书的看法先吧,整体的来说,内容还是不错的,就是感觉有点老了(作为前端小白,也可能是自身水平有限,未能体会到其中真意).看这本书的过程中也是写了挺多代码用以测试的,并且对本

Oracle 相关知识点结构图

最近在学Oracle数据库,制作了些结构图方便记忆!主要涉及到Oracle数据类型,Oracle的表操作以及Oracle的游标,还有的之后再分享...... Oracle 数据类型 因为图片上只能看到结构,一些知识点看不了,建议大家点击这个链接,去看源文件:http://naotu.baidu.com/viewshare.html?shareId=atvuh8jmlb4g Oracle表操作 链接:http://naotu.baidu.com/viewshare.html?shareId=atv