
重温C++primer笔记
Tsinting
这个作者很懒,什么都没留下…
展开
-
数据抽象和封装
类背后蕴含的基本思想是数据抽象和封装。 数据抽象是一种依赖于接口和实现分离的编程技术。类设计者必须关心类是如何实现的,但使用该类的程序员不必了解这些细节。相反,使用一个类型的程序员仅需要了解类型的接口,他们抽象地考虑该类型做什么,而不必具体地考虑该类型如何工作。 封装是一项将低层次的元素组合起来形成新的、高层次实体的技术。函数是封装的一种形式:函数所执行的细节行为被封装在函数本身这个更原创 2017-03-27 14:56:49 · 1060 阅读 · 0 评论 -
显式指定模板实参
1、 指定返回类型的一种方式是引入第三个模板形参,它必须由调用者显式指定。这个版本增加了一个模板形参以指定返回类型。只有一个问题:没有实参的类型可用于推断 T1 的类型,相反,调用者必须在每次调用 sum 时为该形参显式提供实参。为调用提供显式模板实参与定义类模板的实例很类似,在以逗号分隔、用尖括号括住的列表中指定显式模板实参。显式模板类型的列表出现在函数名之后、实参表之前。原创 2017-03-31 18:32:57 · 925 阅读 · 0 评论 -
模板实参推断与函数指针
原创 2017-03-31 18:22:33 · 360 阅读 · 0 评论 -
模板实参的转换
1、 模板是一个蓝图,它本身不是类或函数。编译器用模板产生指定的类或函数的特定类型版本。产生模板的特定类型实例的过程称为实例化,这个术语反映了创建模板类型或模板函数的新“实例”的概念。2、 使用函数模板时,编译器通常会为我们推断模板实参。3、 一般而论,不会转换实参以匹配已有的实例化,相反,会产生新的实例。除了产生新的实例化之外,编译器只会执行两种转换:(1)const 转换:接受原创 2017-03-31 18:18:31 · 461 阅读 · 0 评论 -
非类型模板形参
原创 2017-03-31 18:13:09 · 560 阅读 · 0 评论 -
类型模板形参
1、 模板定义以关键字template 开始,后接模板形参表,模板形参表是用尖括号括住的一个或多个模板形参的列表,形参之间以逗号分隔。模板形参表不能为空。2、 模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。非类型形参跟在类型说明符之后声明。类型形参跟在关键字 class 或 typename 之后定义,例如,class T 是名为 T 的类型形参,在这里 class原创 2017-03-31 16:24:52 · 3908 阅读 · 0 评论 -
函数的默认实参
既可以在函数声明也可以在函数的定义中指定默认实参。但是在一个文件中,只能为一个形参指定默认实参一次。例如下面的例子是错误的。//ff.hint ff(int =0);//ff.cc#include"ff.h"int ff(int i=0){ }//error如果在函数定义的形参列表中提供默认实参,那么只有在包含该函数定义的源文件中调用该函数时默认实参才是有效的,所以通常应在函数声明中原创 2017-03-15 18:32:50 · 560 阅读 · 0 评论 -
句柄类
1、 C++ 中一个通用的技术是定义包装(cover)类或句柄类。句柄类存储和管理基类指针。指针所指对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用指针执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象的类型而变化。因此,句柄的用户可以获得动态行为但无须操心指针的管理。2、 迄今为止,我们已经使用过的使用计数式类,都使原创 2017-03-31 10:47:14 · 452 阅读 · 0 评论 -
纯虚函数
1、 在函数形参表后面写上 =0 以指定纯虚函数。2、 将函数定义为纯虚能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。重要的是,用户将不能创建抽象类型的对象。试图创建抽象基类的对象将发生编译时错误。原创 2017-03-30 20:50:07 · 335 阅读 · 0 评论 -
继承与作用域
1、 每个类都保持着自己的作用域,在该作用域中定义了成员的名字。在继承情况下,派生类的作用域嵌套在基类作用域中。如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义。正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好象这些成员是派生类成员一样。2、 与基类成员同名的派生类成员将屏蔽对基类成员的直接访问。3、 可以使用作用域操作符访问被屏蔽的基类成员原创 2017-03-30 20:40:08 · 963 阅读 · 0 评论 -
复制控制和继承
1、 如果派生类显式定义自己的复制构造函数或赋值操作符,则该定义将完全覆盖默认定义。被继承类的复制构造函数和赋值操作符负责对基类成分以及类自己的成员进行复制或赋值。 2、 如果派生类定义了自己的复制构造函数,该复制构造函数一般应显式使用基类复制构造函数初始化对象的基类部分。3、 赋值操作符必须防止自身赋值。假定左右操作数不同,则调用 Base 类的赋值操作符给基类部分赋值。该操原创 2017-03-30 19:33:11 · 374 阅读 · 0 评论 -
派生类构造函数
1、 构造函数和复制控制成员不能继承,每个类定义自己的构造函数和复制控制成员。像任何类一样,如果类不定义自己的默认构造函数和复制控制成员,就将使用合成版本。2、 派生类的合成默认构造函数除了初始化派生类的数据成员之外,它还初始化派生类对象的基类部分。基类部分由基类的默认构造函数初始化。3、 派生类构造函数的初始化列表只能初始化派生类的成员,不能直接初始化继承成员。相反派生类构造函数通原创 2017-03-30 18:35:22 · 827 阅读 · 0 评论 -
转换与继承
1、我们已经看到,可以将派生类型的对象传给希望接受基类引用的函数。也许会因此认为对象进行转换,但是,事实并非如此。将对象传给希望接受引用的函数时,引用直接绑定到该对象,虽然看起来在传递对象,实际上实参是该对象的引用,对象本身未被复制,并且,转换不会在任何方面改变派生类型对象,该对象仍是派生类型对象。将派生类对象传给希望接受基类类型对象(而不是引用)的函数时,情况完全不同。在这种情况下,形参的类型是原创 2017-03-30 13:27:50 · 366 阅读 · 0 评论 -
类模板成员函数
原创 2017-03-31 18:55:24 · 417 阅读 · 0 评论 -
类模板成员函数的实例化
1、 与其他函数模板不同的是,在实例化类模板成员函数的进修,编译器不执行模板实参推断,相反,类模板成员函数的模板形参由调用该函数的对象的类型确定。例如,当调用 Queue 类型对象的 push 成员时,实例化的push 函数为 void Queue::push(constint &val)。对象的模板实参能够确定成员函数模板形参,这一事实意味着,调用类模板成员函数比调用类似函数模板更灵活。用模板原创 2017-03-31 19:08:59 · 3153 阅读 · 0 评论 -
类模板的非类型形参
非类型模板实参必须是编译时常量表达式。原创 2017-03-31 19:13:36 · 598 阅读 · 0 评论 -
类的简述
最简单地来说,类就是定义了一个新的类型和一个新的作用域。 在类的内部,声明成员函数是必需的,而定义成员函数是可选的。在类内部定义的函数默认为inline。将关键字const加在形参列表之后,就可以将成员函数声明为常量: double price()const; const成员不能改变其所操作对象的数据成员。const必须同时出现在声明和定义中,若只出现在其中一处会导致编译原创 2017-03-27 14:38:50 · 340 阅读 · 0 评论 -
迭代器所提供的运算
//所有标准库容器类型都支持的运算*iter;iter->num;++iter;iter++;--iter;iter--;iter1==iter2;iter1!=iter2;//只有vector和deque容器的迭代器支持的操作iter+n;iter-n;iter1+=iter2;iter1-+iter2;iter1-iter2;,>=//关系操作符只适用于ve原创 2017-03-17 10:12:18 · 444 阅读 · 0 评论 -
顺序容器适配器
标准库提供三种顺序容器适配器,分别是queue, priority_queue, stack。适配器是标准库中通用的概念,包括容器适配器、迭代器适配器和函数适配器。本质上,适配器是使一事物的行为类似于另一事物行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。例如栈适配器可使任一种顺序容器以栈的方式工作,即容器适配器是基于一种基础容器类型实现的。//适配器的原创 2017-03-17 12:38:41 · 369 阅读 · 0 评论 -
顺序容器操作汇总
//构造函数C c; //创建一个名为c的空容器C c(c2); //创建容器c2的副本,c和c2必须具有相同的容器类型并存放相同的元素类型。C c(b,e); //创建c,其元素是迭代器b和e范围内的元素副本,此种方式不要求容器类型相同,容器内元素类型也可以不同,但要相互兼容C c(n,t); //用n个值为t的元素创建容器c,t类型必须与容器的元素类型兼容,此种构造方式只适用于顺序容器原创 2017-03-17 11:42:11 · 308 阅读 · 0 评论 -
顺序容器中添加元素
//所有顺序容器都支持push_back操作(vector,list,deque)//只有list和deque容器适用于push_front操作//insert操作c.insert(p,t);//在迭代器p前插入值为t的新元素,返回指向新元素的迭代器c.insert(p,n,t);//在迭代器p前插入n个值为t的新元素,返回voidc.insert(p,b,e);//在迭代器p前插入原创 2017-03-17 10:47:29 · 445 阅读 · 0 评论 -
指向函数的指针
一 指向普通函数的指针先来看一个函数:[cpp] view plain copyint Sum(int a, int b) { return a + b; } 这个函数,调用方式可以如Sum(1, 2);若要表示函数的指针,可以用&Sum,也可以将Sum前边的地址操作符&去掉,对于普通函数原创 2017-03-15 20:23:56 · 386 阅读 · 0 评论 -
函数重载
出现在相同作用域的两个函数,如果具有相同的名字而形参列表不同,则称为重载函数。如果两个函数声明的返回类型和形参列表完全相同,则将第二个函数声明视为第一个的重复声明。如果两个函数的形参列表相同,但返回类型不同,则第二个声明是错误的,即不能仅仅基于不同的返回类型来实现重载。同样,形参只有是否为const的区别的也无法重载,但值得注意的是,形参与const形参的等价性只适用于非引用形参。有const原创 2017-03-15 19:28:49 · 349 阅读 · 0 评论 -
内联函数
内联函数的定义对编译器来说必须是可见的,以便编译器能够在调用点内联展开该函数的代码。此时内联函数仅有原型是不够的。所以内联函数在程序中可以多次定义。如若某个源文件需要使用某一内联函数,则必须在该源文件中再次进行定义,这样并不会引发重复定义的错误,但前提是任何一个源文件中内联函数的定义至多出现一次且每个源文件中的定义都必须是相同的,即遵循“单一定义规则”。一般把内联函数的定义放在头文件中,可以确原创 2017-03-15 19:01:15 · 544 阅读 · 0 评论 -
头文件中类的成员函数的声明和定义
原文:http://blog.youkuaiyun.com/dengm155/article/details/51692285--------------------------------------------------------————————————————————————————————————————————先来做一个实验,你在一个头文件中定义一个类,然后把内中的一个函数的实现转载 2017-03-15 18:23:10 · 7146 阅读 · 0 评论 -
关于头文件中的重复包含和重复定义
对于重复包含错误,一般使用#ifndef来避免。值得注意的是,#ifndef起到的效果是防止一个源文件两次包含同一个头文件,而不是防止两个源文件包含同一个头文件。网上很多资料对这一细节的描述都是错误的。事实上,防止同一头文件被两个不同的源文件包含这种要求本身就是不合理的,头文件存在的价值就是被不同的源文件包含。也就是说对于A.cpp和B.cpp两个源文件都包含了head.h的头文件时,条件编译原创 2017-03-15 17:40:11 · 3539 阅读 · 2 评论 -
基本语言(二)
1、在全局作用域定义在非const变量在整个程序中都能访问。而全局作用域定义的const变量不能被其他文件访问,除非通过指定const变量为extern://file1.ccextern const intx=fcn(); //file2.ccextern const intx;for(inti=0;i非const变量默认为extern,要使const变量能够在别的文件原创 2017-03-05 17:51:59 · 256 阅读 · 0 评论 -
类模板中的友元声明
1、 在类模板中可以出现三种友元声明,每一种都声明了与一个或多个实体友元关系: (1)普通非模板类或函数的友元声明,将友元关系授予明确指定的类或函数。 (2) 类模板或函数模板的友元声明,授予对友元所有实例的访问权。 (3) 只授予对类模板或函数模板的特定实例的访问权的友元声明。2、 非模板类或非模板函数可以是类模板的友元。这个声明是说,FooBar 的成员和 fcn 函数可以访问 Bar原创 2017-03-31 19:37:13 · 918 阅读 · 0 评论 -
友元与继承、静态成员与继承
1、友元关系不能继承。基类的友元对派生类的成员没有特殊访问权限。如果基类被授予友元关系,则只有基类具有特殊访问权 限,该基类的派生类不能访问授予友元关系的类。2、如果基类定义 static 成员,则整个继承层次中只有一个这样的成员。无论从基类派生出多少个派生类,每个 static 成员只有一个实例。 static 成员遵循常规访问控制:如果成员在基类中为 private,则派生类不能访问它。假原创 2017-03-30 12:49:40 · 627 阅读 · 0 评论 -
公用、私有和受保护继承
1、 如果成员在基类中为private, 则只有基类和基类的友元可以访问该成员。派生类不能访问基类的 private 成员,也不能使自己的用户能够访问那些成员。如果基类成员为 public 或 protected,则派生列表中使用的访问标号决定该成员在派生类中的访问级别:(1)如果是公用继承,基类成员保持自己的访问级别:基类的 public 成员为派生类的 public 成员,基类的 prote原创 2017-03-30 12:42:37 · 613 阅读 · 0 评论 -
函数的返回值
函数的返回值用于初始化在调用函数处创建的临时对象。在求解表达式时,如果需要一个地方存储器运算结果,编译器会创建一个没有名字的的对象,这就是临时对象。 用函数返回值初始化临时对象与用实参初始化形参的方法是一样的。如果返回类型不是引用,在调用函数的地方会将函数的返回值复制给临时对象。当函数返回非引用类型时,其返回值可以是局部对象,也可以是求解表达式的结果。 当返回引用类型时,没有赋原创 2017-03-10 22:54:47 · 451 阅读 · 0 评论 -
C++类中的数据成员能否在定义类的时候就初始化?
class A{private: int a=1;};即上述关于类的定义正确与否?一般而言,类中的数据成员在定义类的时候是不能初始化的。这是一个可以值得探讨的话题,每个人的解释都不一样,大部分人都认为这是编译语法的规定,那么有没有考虑为什么会有这个规定呢? 个人认为可能的原因有: (1)类只是一个抽象类型,并不是实体的东西,利用这个抽象类型会原创 2017-03-06 17:31:42 · 16842 阅读 · 0 评论 -
const引用形参
在函数中,应该将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不太灵活。这样的形参既不能用const对象初始化,也不能用字面值或者产生右值的表达式实参初始化。原创 2017-03-10 18:29:07 · 530 阅读 · 0 评论 -
可变数据成员
有时我们希望类的数据成员(甚至在const函数内)可以修改。这可以通过将它们声明为mutable来实现。 可变数据成员永远不能为const,甚至当它是const对象的成员时也如此。 class screen{ public: // privita: mutable int str; //may change in a const members};void screen原创 2017-03-27 15:23:23 · 524 阅读 · 1 评论 -
类的声明与定义
可以声明一个类而不定义它。 class screen;//声明而未定义 在声明之后、定义之前,类screen是一个不完全类型,即已知screen是一个类型,但不知道包含哪些成员。 不完全类型只能以有限的方式使用。不能用来定义该类型的对象,只能用于定义指向该类型的指针及引用,或用于声明(不能是定义)使用该类型作为形参类型或者返回类型的函数。 在创建对象之前,必须完整地定义该类原创 2017-03-27 15:07:34 · 6525 阅读 · 0 评论 -
命名的强制类型转换
命名的强制类型转换符号的一般形式如下:cast-name(expression)其中cast-name为static_cast, dynamic_cast, const_cast和reinterpret_cast之一,type为转换目标类型,expression为被强制转换的值。1、 dynamic_cast. dynamic_cast支持运行时识别指针或者引用所指向的对原创 2017-03-10 17:03:36 · 291 阅读 · 0 评论 -
C++声明和定义
C++程序通常由许多文件组成,为了让多个文件访问相同的变量,C++区分了声明和定义。变量的定义用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且仅有一个定义。声明用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过extern关键字声明变量而不定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern:ext原创 2017-03-05 16:33:55 · 370 阅读 · 0 评论 -
multimap和multiset容器
multimap和multiset类型允许一个键对应多个实例。multimap和multiset支持的操作分别与map和set操作相同,只是multimap不支持下标运算。//元素的添加和删除由于键不是唯一的,所以每次insert总会添加一个元素。 带有一个键参数的erase将删除拥有该键的所有元素,并返回删除元素的个数。//查找元素multimap m;m.count(k)原创 2017-03-18 20:05:38 · 367 阅读 · 0 评论 -
set容器
set容器只是单纯的键的集合,且存储的键值必须是唯一的,而且不能修改。set容器不提供下标操作符。可通过find和count操作来判断某个元素是否存在。原创 2017-03-18 19:46:10 · 351 阅读 · 0 评论 -
map容器
map容器是键-值对的几何。map类型通常可理解为关联数组。map中的每个元素类型为pair类型,pair类型定义在utility头文件中。//pair类型提供的操作 pair p;pair p(V1,V2);make_pair(V1,V2);p.firstp.second接下来是map的相关操作//构造函数 map m; map m(m2); //创建m2的副本原创 2017-03-18 19:36:04 · 395 阅读 · 0 评论