写代码时遇见了成员初始化列表,突然忘了成员函数为什么要使用成员初始化列表然后翻了翻书总结一下:
在派生类构造函数中对派生类成员进行初始化时一定要使用成员初始化列表,为什么呢?因为要初始化基类的成员,但为什么不直接在构造函数内进行初始化而非要发明一个这样的语法呢?因为基类对象要在程序进入派生类的构造函数之前构造完成,所以要使用成员初始化列表先初始化基类的成员,一般是直接调用基类的构造函数就行。
class Base
{
private:
int a;
public:
Base(int b){a=b;}
....
}
class ase:public Base
{
private:
int c;
public:
ase(int k,int m):Base(m){c=k;}
....
}
所以说创建派生类对象时,程序首先创建基类的对象,如果没有显式地调用基类的构造函数,则使用默认的基类构造函数对基类进行初始化。
在总结成员初始化列表时突然又想到了友员成员函数,因为也是跟成员初始化列表差不多,初始化时要注意顺序。
友元的主要作用是定义一个不是这个类的成员函数的函数用来访问这个类的私有数据,可以将一个类作为另一个类的友元类,这样这个类的一些成员函数就可以在函数中直接访问另一个类的私有数据。还可以将一个类的成员函数作为另一个类的友元成员函数,这样定义的时候一定要注意顺序。
例如,将类BASS中的set函数作为类AASS类中的友元成员函数:
class AASS
{
friend void BASS::set(AASS &a,int c);
}
这样问题就出现了
编译器首先要知道BASS是一个类,所以需要这样定义类:
class AASS
class BASS
{
....
}
class AASS
{
....
}
这种方法称为前向声明,假如BASS类中有些函数调用了AASS类的一些方法,则应该将这些BASS中的函数定义在AASS之后。
接下来总结一下基类和派生类有关的知识点:
1 基类指针或引用可以指向派生类(这是调用虚函数的方法之一,使用一个基类类型的指针,赋给不同的地址可以调用不同的虚函数)
2 基类都要声明一个虚析构函数。因为如果不声明一个虚析构函数,则只会析构派生类而不会析构基类对象。
3 动态联编和静态联编 动态联编一般指的是虚函数,虚函数的处理方式是会生成一个虚函数表。
还有一个问题是继承和动态内存分配
如果基类使用了new进行动态内存分配,并重新定义了赋值和复制构造函数,那么将怎样影响派生类呢?
这会分两种情况
1 如果派生类的成员不是指针类型,不需要使用new来进行动态内存分配,那么完全没有必要再为派生类重新定义赋值和复制构造函数,因为如果要对派生类进行赋值和复制的话将使用默认的,而默认的将调用基类的复制和赋值来处理基类的部分。而且析构函数也不用重新定义。
2 如果派生类包含有指针类型,需要使用new来进行动态内存分配,那么必须为派生类重新定义复制构造函数,赋值运算符,析构函数。那么这些函数要如何处理基类部分呢?
对于析构函数直接处理派生类的部分,派生类将调用基类的析构函数
对于复制构造函数,那么要使用成员初始化列表初始化基类的部分。
对于赋值运算符,也要处理基类的部分,但不是使用成员初始化列表,而是在派生类重新定义赋值运算符内使用 BASS::operator=(hs);初始化基类。