假设结构指针p已定义并正确赋值,其指向的结构变量有一个成员是int型的num,则语句 *p.num = 100; 是正确的。 错((*p).num = 100;(因为.的优先级高于*);或者p→num,也可以)
在生成对象数组时,将针对每个数组元素按其下标的排列顺序依次调用一次构造函数,调用的次数等于数组元素的个数
常成员函数可以访问const数据成员,也可以访问非const数据成员,注意是只是访问,但不可以修改
由于静态成员函数不属于某个特定的对象,因此。不能像一般的成员函数那样随意的访问对象中的非静态数据成员。只能引用类中声明的静态数据成员。如果要引用非静态数据成员,可通过对象引用。
1、const 数据成员不能在类内定义时初始化,在类外初始化也不行。通常通过构造函数初始化。
2、static 数据成员不能在类内初始化,在类外初始化。因为static成员不属于任何一个对象。
类的静态数据成员在 类内只能声明,定义和初始化必须在类外
3、static const 数据成员可以在类内初始化。但一般仅仅限于整形。
对象赋值
- 同一个类的对象之间可以相互赋值,默认情况下,进行的是对象成员之间的复制,也称为【按位复制】或【浅复制】。
- 当类的数据成员中没有指针类型的变量时,直接对两个对象进行赋值没有问题。
- 但是一旦类的数据成员含有指针变量,那么直接对这两个对象进行赋值操作之后,这两个对象的指针都将指向同一块内存。这时,一旦其中一个对象生存期结束,释放该内存,那么另一个对象的指针就变成了野指针!这对程序危害很大。
拷贝构造函数的声明:类名(类名 &对象名)
解决上述问题的方法就是在类中添加拷贝构造函数。
- 拷贝构造函数是一个特殊的构造函数,当采用一个对象初始化另一个对象时,将自动调用拷贝构造函数。他与构造函数唯一的区别就是,其参数是当前类的引用,而且必须是一个引用。
- 注意,拷贝构造函数能解决用一个对象初始化另一个对象的问题,其在创建对象时被调用,但是不能处理对象之间的赋值操作(对象初始化与赋值是两个不同的操作)。
若new一个对象数组,那么用delete释放时应该写[],否则只delete一个对象(调用一次析构函数)。
常数据成员的值必须初始化,且不能改变。
当用一个对象去初始化同类的另一个对象时,要调用拷贝构造函数。
对单目运算符重载为友元函数时,可以说明一个形参。而重载为成员函数时,不能显式说明形参。 不能重载的运算符五个: . (成员访问运算符) *(成员指针访问运算符) :: (域) sizeof ?:(条件运算符)只能重载为成员函数 ()、[]、->或者=赋值运算符
运算符重载函数的参数个数与重载方式有关:
- 重载为成员函数时,参数个数为运算符数目减一。 二元成员运算符
- 重载为友元函数时,参数个数为运算符数目。 一元友元运算符
针对<<、>>运算符只可以 重载为友元函数或普通函数
虚函数的定义
虚函数就是在基类中被关键字 virtual 说明,并在派生类中重新定义的函数。
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
虚函数的定义是在基类中进行的,它是在基类中在那些需要定义为虚函数的成员函数的声明中冠以关键字 virtual 。
-
虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数,因为虚函数调用要靠特定的对象来决定该激活哪个函数。
-
使用对象名和点运算符的方式调用虚函数是在编译时进行的,是静态联编,没有利用虚函数的特性。只有通过基类指针访问虚函数时才能获得运行时的多态性。
C++类体系中,不能被派生类继承的有 析构函数,构造函数,赋值运算符重载函数
缺省构造函数,拷贝构造函数,拷贝赋值函数,以及析构函数这四种成员函数被称作特殊的成员函数。这4种成员函数不能被继承
构造函数不可以定义为虚函数
在公有继承的情况下,在派生类中能够访问的基类成员包括 公有成员和保护成员
在公有派生的情况下,有以下三条赋值兼容规则(是指在需要基类对象的任何地方,都可以使用 公有派生类的对象 来替代)。
- 派生类的对象可以赋值给基类对象。
- 派生类对象可以用来初始化基类引用。
- 派生类对象的地址可以赋值给基类指针,亦即派生类的指针可以赋值给基类的指针。(上面三条反过来是不成立的。例如,不能把基类对象赋值给派生类对象。)
Eg:
下列有关类型兼容规则的描述中,错误的是:
A.派生类的对象可以隐含转换为基类对象
B.派生类的对象可以初始化基类的引用
C.派生类的指针可以隐含转换为基类的指针
D.派生类的对象可以被基类的对象初始化
C++中建立派生类对象时构造函数的调用顺序
- 建立派生类对象时,派生类构造函数的调用顺序如下:( 多重继承派生类的构造函数,需要调用所有的基类构造函数来完成各基类数据成员的初始化。)
- 执行基类的构造函数。当派生类有多个基类时,处于同一层次的各个基类的构造函数的调用顺序取决于定义派生类声明的顺序(从左至右),而与在派生类构造函数的成员初始化列表中给出的顺序无关。如果派生类的基类也是一个派生类,则每个派生类值需负责它的直接基类的构造,依次上溯。
- 执行成员对象的构造函数(如果有的话)。当派生类中有多个成员对象时,各个成员对象构造函数的调用顺序也取决于在派生类中定义的顺序(自上而下),而与在派生类构造函数的成员初始化列表中给出的顺序无关。
- 执行派生类的构造函数。
派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是基类中必须有默认的构造函数或者根本就没有定义构造函数。
如果基类有无参构造函数,则派生类的构造函数就可以不带初始化列表 (T)
- 派生类析构函数的调用顺序:
- 执行派生类的析构函数,对派生类新增普通成员进行清理。
- 调用成员对象析构函数,对派生类新增的成员对象进行清理。
- 调用基类的析构函数,对基类进行清理。
派生类析构函数的定义与基类无关,与没有继承关系的类中的析构函数的定义完全相同。它只负责新增成员的清理工作,系统会自己调用基类及成员对象的析构函数进行相应的清理工作。
以下说法正确的是?
A.子对象都是通过无参构造函数初始化的
B.派生类对象的构造函数是先于基类的构造函数被调用的
C.由多个基类派生时,基类构造函数的调用顺序,取决于定义派生类时,派生列表中的基类声明顺序
D.由多个基类派生时,子对象所属类的构造函数调用顺序,取决于基类的定义顺序
实现动态联编用父类指针或引用指向子类对象
抽象类的规定
- 抽象类只能用作其他类的基类,不能建立抽象类对象。
- 抽象类不能用作参数类型、函数返回类型或显式转换的类型。
- 可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性 ,可以定义指向抽象类的指针和引用,但不能定义抽象类对象
假设 Aclass为抽象类,下列正确的说明语句是 Aclass * p ;
派生类对象和基类对象的关系:
- 派生类对象可以向基类对象赋值.
- 派生类对象可以替代基类对象向基类对象的引用进行赋值或初始化
- 如果函数的参数是基类对象或基类对象的引用,相应的实参可以用子类对象
- 派生类对象的地址可以赋值给指向基类对象的指针变量,即使说指向基类对象的指针变量也可以指向派生类的对象



