Classes and Data Abstraction (类和数据抽象)
class: ·声明:
Access Authority (访问权限): ·public:对外接口
·private:只允许类的成员函数访问 ·protected:
构造函数:创建对象本身 ·名字与类的名字相同
·主要用来在创建对象时初始化对象 ·即为对象成员变量赋初始值 ·不能有返回类型
·一般情况下只有一个构造函数被调用 ·可以设定初始值也可以不设定 【
类似这种就是什么都不做不设定初始值的构造函数】
Default constructor(默认构造函数): ·一个类里面只有一个
析构函数: ·类的成员函数
·delete系统对象:在对象生命周期结束时回收占用的内存空间
·会有默认的析构函数存在(生命期结束时,会自动执行析构函数) ·如果 显示定义:加~ ·一定无参数
·无重载 每一个类只有一个析构函数
析构函数的作用正好与构造函数相反。当对象超出其作用范围,对应的内存空间被系统回收或被程序用delete删除时,析构函数将被调用。
当对象为指针对象时, delete指针变量,析构函数只释放本身空间,不能主动释放指针指向的外部的空间
这里看配图吧:
构造函数与析构函数的调用:
构造函数和析构函数都是自动被调用,顺序取决于作用域 (1) 在全局范围中定义的对象,它的构造函数在文件中的所有函数(包括main函数)执行之前调用。但如果一个程序中有多个文件,而不同的文件中都定义了全局对象,则这些对象的构造函数的执行顺序是不确定的。当main函数执行完毕或调用exit函数时(此时程序终止),调用析构函数。
(2) 如果定义的是局部自动对象,则在建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束、对象释放时先调用析构函数。 (3) 如果在函数中定义静态(static)局部对象,则只在程序第一次调用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。
+++++++++++++++++++++++++++++++试卷中曾经出现的题目++++++++++++++++++ 以下说法哪个是错误的?
·A 它们有相同的名字,除了符号(~) ·B 它们一般在一个对象里只会被调用一次 ·C 它们都能接受默认参数(错误)(析构函数不接受任何参数) ·D 即使没有在类里面定义,也可以自动调用
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
拷贝构造函数必须以引用的形式传递(参数为引用值) 其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。
引用
定义引用的表示方法与定义指针相似,只是用&代替了*
Point &pt2=pt1; 定义了pt2为pt1的引用。通过这样的定义,pt1和pt2表示同一对象。
需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。【所以说其实pt1和pt2是一个地址,改变了一个就会改变另一个?】
· 引用不可以改变指向,对一个对象\至死不渝\;但是指针可以改变指向,而指向其它对
象
· 引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针本身的大
小,4个字节
· 指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名,引用不
改变指向。
· 指针用于指向对象,保存的是另一个对象的地址;
引用and指针的区别【答案来自百度】
1. 引用访问一个变量是直接访问,而指针是间接访问。
【引用一步到位,指针要经过两步的意思?】 比如: int a = 5; int &b = a; //变量名是b,而b也是a,所以b跟a占有相同的内存空间
int *p = &a; //变量名是p,是一个指针,占有自己的内存空间,然后内容是指向a的
指针,要对a操作必须用*p才能操作,而上面直接用b就可以操作
2. 引用是一个变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间。
【变量的别名的意思是,通过引用可以直接到达变量的内存地址?】
意思是两个是同样的东西,在内存中占有相同的内存单元,相当于你名字是A,乳名是B,A相当于变量名,B相当于别名,A也是你,B也是你,AB是完全一样的东西。 3.引用在开始的时候就绑定到了一个内存空间(开始必须赋初值),所以他只能是这个内存空间的名字,而不能改成其他的。指针在任何时刻都可以改变自己的指向
+++++++++++++++++++++++++++++试卷中出现过的题目++++++++++++++++++++++++ 引用与指针的区别:
(11年)
A引用指向整个对象(??),而指针仅仅指向对象的地址(错误) B指针可以指向NULL,引用不能
C指针可以被分配NULL,直接,而引用不能被指定为NULL,必须在初始化时被分配。 D指针是一个变量,可以存储一个内存地址,引用与它指向的对象有相同的内存地址 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
拷贝构造函数:基于同一类的其他对象的构建及初始化 ·形参类型为该类类型本身且参数传递方式为按引用传递。 ·用一个已存在的该类对象初始化新创建的对象。 ·每个类都必须有拷贝构造函数:
·用户可根据自己的需要显式定义拷贝构造函数。
·若用户未提供,则该类使用由系统提供的缺省拷贝构造函数。
·缺省拷贝构造函数使用逐位复制方式利用已存在的对象来初始化新创建的对象(相当于赋值= )。
·拷贝构造函数必须以引用的形式传递(参数为引用值) 其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。
【简单一句话,若不是传地址,递归就是无限循环】
const
当变量只作为值存在 而不需要进行改变时 在编程习惯上 加const
const指定的对象是不能修改的(要有初始值) 只要尝试改变const的都会被看做编程语法错误
只有被声明为const的成员函数才能被一个const类对象调用 【就是有const的函数才能调用类中有const的数据?】 比如你写一个Student类,然后这样定义: const Student stu;
那么,这个stu就是一个常对象,它只能调用const的函数,不能调用不是const的成员函数,自己打一段代码编译一下就明白了。
const对象只能调用const函数
const函数只能调用const对象 不能改变值
const函数是不能改变对象的内容,比如还是Student类 Student stu;
stu.getId() 这个获取学号的过程,stu的内容是不变的。;
对于在类体之外定义的const成员函数我们必须在它的定义和声明中同时指定关键字const 格式
当只是做返回值的函数时 返回值函数 设为const(好习惯)
构造函数和析构函数 不能加const 因为这两个函数要改变变量的内存地址
构造函数要创建对象,析构函数要删除对象,对象本身肯定要发生改变,所以不能是const的,然后内存方面,创建对象要分配内存,删除对象要回收内存。 不涉及对象修改的函数也定义为const
就是我前面说的,如果不改变stu自己的内容,那么就定义为const函数,如果要改变到对象的内容,就不能定义成const函数
不能采用在构造函数中对常数据成员赋初值的方法 要采用成员初始化表
成员初始化表
成员初始化表是由逗号分隔的成员、名字实参对 成员初始化表跟在构造函数的原型后,由冒号开头
成员初始化表和使用构造函数对数据成员进行赋值的操作结果是一样的,但前者是初始化后者是赋值
任何数据成员的初始化都可以使用这种方式 但const的赋值方式是只有这一种 例子如下
组合(Composition)
把对象作为类的成员 对象之间的嵌套关系 对象中包含对象 例子如下(eg. 一个类里面再嵌套一个类)