复习10:类
来源:互联网 发布:讲文明知礼仪主题文章 编辑:程序博客网 时间:2024/05/29 17:52
10.1 引言
10.2 类
10.2.1 成员函数
10.2.2 访问控制
10.2.3 构造函数
构造函数可以有多种重载形式,如:
10.2.4 静态成员
静态成员--包括函数和数据成员--都必须在类外定义,如 注:在vs的编译器上静态函数成员可以在类内定义,但为了程序的可移植性不建议这样做。
10.2.5 类对象的复制
按照默认的方式,类对象的复制就是其中各个成员的复制。如果对于类X这种方式不恰当,就需要定义一个复制构造函数(也成拷贝构造函数)X::X(const X&).
类似的,类成员也可以通过赋值运算符进行按默认方式的复制。
10.2.6 常量成员函数
常量成员函数表明它不会修改对象的状态。一切对象都可以嗲用cosnt成员函数,而const对象缺不能调用非const函数(这个很自然)。
10.2.7 自引用
每一个非静态的函数都知道它在哪个对象里调用,因此可以显式地返回该对象。如 表达式*this引用的就是这个函数这次调用所在的对象。
在一个非静态的成员函数里,关键字this是一个指针,指向该函数所在的对象。在类X的非const成员函数里,this的类型是X*,在const成员函数里,this的类型是cosnt X*,防止修改该对象。在静态的成员函数里使用this是没有意义的,c++在静态成员函数里不设置这个关键字,即无法使用this。this并不是一个常规的变量,更不是一个左值变量,不能取得他的地址或给他赋值。
10.2.7.1 物理和逻辑的常量性
偶然有这种情况,一个成员函数在逻辑上是const,但它却仍然要改变某个成员的值。对于延迟求值技术,这个问题更常见。比如成员函数要返回对象的某个性质,逻辑上它应是const函数,但是这个性质可能已经过期需要重新计算,这是该函数就需要先做修改后再返回新的值。我们可以通过const_cast把this的const属性去掉,这种不优美的方式存在着潜在的风险,如:
10.2.7.2 可变的--mutable
为了避免无定义的行为,只有将数据声明为mutable。存储描述符mutable特别说明这个成员需要以可以更新的方式存储--即使他是某个const对象的成员。这使得const集合中出现一些特例。
如果这些特例不是太多,使用mutable是最合适的。但是在一个对象在逻辑上保持为cosnt的同时,其中大部分都要修改,那么最好将这些需要修改的数据放入里外一个独立的对象里,并间接地访问它。
10.2.8 结构和类
一个struct也就是一个类,但其默认成员是公用的。下面两个声明完全等价。
10.2.9 在类内部的函数定义
如果一个函数是在类定义的内部定义的,他就是一个在线成员函数。也就是说,在内部定义的成员函数应该是小的,频繁使用的函数。也可以在类外显式的声明一个成员函数是在线的。
10.3 高效的用户定义类型
这里给出一段代码,我想讨论下其他方面的细节 这些细节的描述相当混乱,在此记下这些疑惑后来能有个清晰的解答。
首先看下static变量。这里只讨论非局部的static变量(局部的static用法很简单,略去)。static变量存放在静态数据区,寿命为程序的整个运行过程,并收相关作用域的约束。使用sizeof求得的大小并不包括占用静态数据区的大小(这跟sizeof有关系,应该给深入的认识sizeof)。普通的递归定义是不允许的,因为编译器要知道每个类型的大小,以便在栈上给它分配空间,编译器无法计算递归定义类型的大小,所以这就被c++禁止了。但是对于static就不同了,static变量不在栈上分配,因此允许static形式的递归定义(在静态数据区上怎么分配呢?关于程序的内存布局还是很模糊,希望做个专题解决它)。
现在说说对enum的看法,enum就是一个static const的变量,关于占用空间的大小和有效性已在前面讨论过了。类中enum成员属于类类型的一部分,不单属于某个对象。
10.3.1 成员函数
10.3.2 协助函数
协助函数并非是类的成员函数,而是处理类常用的函数,如计算两个两个日期之间的天数,求一周后的日期等等。也可以将他们做为类的成员函数,但这样会使得类的界面复杂,可以考虑将这些协助函数和类放在同一个名字空间里。用户包含了该名字空间后就可以方便的使用他们了。
10.3.3 重载的运算符
10.3.4 具体类型的意义
我们把像Date这样简单用户定义类型称作具体类型,是为了区别抽象类型和类层次结构,也是为了强调它们与int和char等内部类型的相似性。如果有一个非常好的编译器,像Date这样的具体类型将不会带来隐形的时间或者空间上的额外开销。具体类型的大小在编译的时候已知晓,可以在运行栈上分配存储。
10.4 对象
10.4.1析构函数
一个类只能有一个析构函数,且析构函数是一个无参函数。当一个自动变量离开作用域时,当一个位于自由存储被删除时,还有在其他类似的情况中,析构函数将被隐式的调用。只有在非常特殊的情况下,用户才需要显式地调用析构函数。程序退出后它占用的所有资源(不含共享的资源)会被OS回收,包括自由存储区。
10.4.2 默认构造函数
默认构造函数就是不需要提供参数的构造函数,包括无参的和带默认值参数的构造函数。一个类只有一个默认构造函数。如果用户声明了默认构造函数,那么就会去使用它;否则,如果有必要,而且用户没有声明任何构造函数,编译器就会设法生成一个。所以声明非默认构造函数时最好也声明默认构造函数,不然在默认构造函数被调用的时候就会产生错误。编译器生成的默认构造函数将隐式地为类类型(class type)成员和它的基类调用有关的默认构造函数,其他的似乎声明都不做。 这里将使用有编译器生成的默认构造函数生成tt,该构造函数为tt.t1以及tt.vt的每个成员调用Table(15)。另一方面,它不会去初始化tt.i和tt.vi,因为他们不是类类型的对象。这是为了与C的兼容和运行时的额外开销。
由于cosnt和引用必须进行初始化,包含const或引用的类就不能进行默认构造,除非程序员显式地提供默认构造函数。内部类型的默认构造函数,参加6.2.8.
10.4.3 构造和析构
一个对象可以通过以下方式建立和销毁:
10.4.4 一个命名的自动对象,程序执行时遇到它的声明时建立,离开它所在的块时销毁。即它生存在它的可见域中。
10.4.5 一个自由存储对象,通过new建立,通过delete销毁。
10.4.6 一个非静态成员对象,作为另一个类对象的成员,它随所属对象一起建立或销毁。
10.4.7 一个数组元素,随着所属数组一起建立或销毁。
10.4.8 一个静态局部变量,在程序执行第一次遇见他的声明时建立一次,在程序终止时销毁一次。
10.4.9 一个全局变量,名字空间的对象,类的静态对象,它们在main开始前建立一次,在程序终止时销毁一次。
10.4.10 一个临时变量,作为表达式求值的一部分被建立,在所属表达式结束时销毁。
10.4.11 一个在分配操作中所提供的参数控制,在分配函数获得的存储区里放置的对象。--稍后讨论
10.4.12 一个union成员,他不能有构造和析构函数。
下面将他们分到各个小节中具体讨论。
- 复习10:类
- 复习10:类-续
- java基础复习--复习总结10
- 复习10:If练习题
- 10-22数据库 复习
- 6-10复习
- javase的复习----10
- CII 复习笔记 10
- 嵌入式复习10
- 二级复习10
- 复习JQ (10)
- HTML5复习 (10)
- C++复习 12 类
- C++复习 类
- C++模板类复习
- 工厂类理论复习
- java类的复习
- 复习 类和对象
- C#数据库事务原理
- hdu1171_多重背包转化为01背包
- Learning OpenGL : (5) Using OpenGL
- 更改ubuntu 10.04风格
- 院赛总结
- 复习10:类
- 转载:C++程序的存储空间布局
- VB 访问Excel简单实例
- givm
- Why Test Driven Development for Embedded?
- I'm here, call me sophie :-)
- 如何设置不一样的奇偶页页眉?
- cout 知识点小体会
- 对浏览器中的context menu的认识.