第9章 关于类和对象的进一步讨论
1. 不能在类定义体中对数据成员初始化,因为类并不是一个实体,而是一种抽象类型,并不占据存储空间,显然无处容纳数据;
2,构造函数不需要用户调用,也不能被用户调用;,在建立对象时由系统自动执行;构造函数一般声明为public.
3,如果用户自己没有定义构造函数,则C++系统会自动生成一个构造函数,只是这个构造函数的函数体是空的,没有参数,不执行初始化操作;
4,带参数的构造函数中的形参,其对应的实参在定义对象时给定;
5,函数具有相同的名字,而参数的个数或者参数的类型不相同,这称为函数的重载;
6,调用构造函数时不必给出实参的构造函数,称为默认构造函数,显然无参的构造函数属于默认构造函数,一个类只能有一个默认构造函数;
如果用户未定义构造函数,则系统会自动提供一个默认构造函数,但它的函数体是空的,不起初始化作用;
7,类的声明是放在头文件中的,用户是可以看到的,而函数的定义时类的实现细节,用户是看不到的。
8,一个类只能有一个默认构造函数,也就是说,可以不使用参数而调用的构造函数,一个类只能有一个;
下面调用有歧义,会出错:
Box();
Box(int= 10;int =10; int =10);
9,在一个类中定义了全部是默认参数的构造函数后,不能再定义重载构造函数了;
10,析构函数不返回任何值,没有函数类型,也没有函数参数,由于没有函数参数,因此它不能被重载;
一个类可以有多个构造函数,但是只能有一个析构函数;
11,析构函数也可以用来执行“用户希望在最后一次使用对象之后所执行的任何操作”
12,如果用户自己没有定义析构函数,C++编译系统会自动生成一个析构函数,但它实际上什么都没干;
13,构造函数的形参名可以和数据成员名同名,但是最好不要这么做;
Student(intnum, string name, char sex):num(num),name(name),sex(sex){}
14.先构造的后析构,后构造的先析构,它相当于一个栈,先进后出;
15,在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在文件中的所有函数(包括main函数)执行之前调用;
16.指向普通函数指针的方法:
数据类型名(*指针变量名)(参数列表)
Void (*p)();
P=fun;
(*p)();//调用fun函数;
17,指向对象成员函数的指针
数据类型名 (类名::*指针变量名)(参数列表);
P2 = &Time::get_time;
注意,后面没有括号,不是p2 = &Time::get_time();这是错误的;
18,常对象中的数据成员为常变量且必须要有初始值,如
Time const t1(12,34,46);
类名 const 对象名[(实参列表);
19,如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数(除了由系统自动调用的隐式的构造函数和析构函数)
20,编译是以源文件为单位的;
21,要引用常对象中的数据成员,只需要将该成员函数声明为const即可;
Void get_time() const;
这表明get_time是一个const型函数,即常成员函数。常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中的数据成员的值;
想要修改,可以把该数据成员声明为mutable,,声明为可变的数据成员,这样就可以用声明为const的成员函数来修改它的值了;
22.只能通过构造函数的参数初始化列表对常数据成员进行初始化;初始化后就不能改变;
23,一般的成员函数可以引用本类中的非const数据成员,也可以修改它们,如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们;
24,常成员函数可以引用const数据成员,也可以引用非const的数据成员,const数据成员可以被const成员函数引用,也可以被非const的成员函数引用;
注意:非const成员函数是不运行引用const对象的数据成员的;
25,常对象只保证其所有数据成员的值不被修改;
26,常成员函数不能调用另一个非const成员函数;
27.对象的复制(复制构造函数)
复制构造函数也是构造函数,但它只有一个参数,这个参数是本类的对象(不能是其他类的对象),而且采用引用的形式;
此复制构造函数的作用就是将实参对象的各个数据成员一一赋给新的对象中对应的数据成员;
28.如果用户自己未定义复制构造函数,则编译系统会自动提供一个默认的复制构造函数,其作用只是简单的复制类中每个数据成员;
29,复制构造函数什么时候被调用:
1. 程序中需要新建一个对象,并用另一个同类的对象对它初始化;
2. 当函数的参数为类的对象时;(传值调用,需要拷贝实参);
3. 函数的返回值是类的对象;也需要复制一个临时对象并传递;
30,静态数据成员是在所有对象之外单独开辟空间,只要在类中定义了静态数据成员,即使不定义对象,也为静态数据成员分配空间,它可以被引用;
31,静态数据成员可以初始化,但只能在类外体进行初始化;
不能用参数初始化列表对静态数据成员初始化,如未对静态数据成员赋初值,则编译系统会自动赋予初值0;
32,静态数据成员既可以通过对象名引用,也可以通过类名来引用(必须是public);
33,与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员;
静态成员函数不属于某一对象,因此静态成员函数没有this指针,既然它没有指向某一对象,就无法对一个对象中的非静态成员进行默认访问;
34,静态成员函数可以直接引用本类中的静态数据成员,在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态数据成员;
35,友元函数:
如果在本类以外的其他地方定义了一个函数(这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数),在类体中用friend对该函数进行声明,此函数就称为本类的友元函数。
一个类的友元函数可以访问这个类的私有成员;
36,只有在正式声明一个类以后才能用它去定义类对象;
37,友元关系不能传递;(用彼此间的朋友不是朋友来比喻);
38,类模板
Template <class numtype>//声明为一个模板,虚拟类型名为numtype
Class Compare //类模板名为Compare
{
Public:
Compare(numtypea ,numtype b)
{x=a;y=b;}
};
39,由于类模板包含类型参数,因此又称为参数化的类,
类模板是类的抽象,类是类模板的实例;
40,用类模板定义对象的方法:
Compare<int> comp(4,7); //类似于容器
41,如果在类模板外部定义成员函数,应写成类模板形式;
Temple <class 虚拟类型参数> //注意这一句后面没有分号来结束
函数类型类模板名<虚拟类型参数>::成员函数名(函数参数表列){….}