1.派生类内存布局,继承了基类什么东西?
先是基类,后是派生类,并且继承了名字作用域和除析构构造之外的所有方法
2. 类的编译程顺序,构造顺序,析构顺序
类的编译程序:先编译类名->成员名->方法体
子类的构造顺序:先构造父类,在构造子类
子类的析构顺序:先析构子类,后析构父类,即先构造的后析构,后构造的先析构
3.基类派生类同名成员之间的关系
重载:重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同
<1>作用域相同
<2>函数名相同
<3>参数列表不同
隐藏:子类会隐藏父类方法中同名的方法
覆盖:子类中和父类中一样的(同返回值,同参数列表,同名)虚成员方法构成覆盖
4.四种类型强转
- const_cast
- static_cast
- dynamic_cast
- reinpreter_cast
5.虚表什么时候产生?存放在哪里?
在编译时期产生,存放在.rodata段
6.纯虚函数->抽象类(抽象类不能定义对象,只能定义指针引用)
virtual void bark() = 0;不提供实现,派生类可以自己写实际的函数,虚基类不能构造函数
7.动多态,静多态
静多态:编译时期决定的多态,如:模板,重载
动多态:运行时期决定的多态,如:继承中的多态
动多态调用的条件有什么?
<1>指针调用或者引用调用
<2>该类型下的虚函数
<3>对象完整
8.基类指针指向子类对象,指针是什么类型?*指针是什么类型?(基类中有虚函数)
class A
{
public:
virtual void show()
{
cout << "A" << endl;
}
};
class B :public A
{
void show()
{
cout << "B" << endl;
}
};
int main()
{
A *a = new B();
cout << typeid(a).name() << endl; //结果是class A *
cout << typeid(*a).name() << endl; //结果是 class B
return 0;
}
定义了一个基类的指针,指向父类的对象,结果如上所示,指针类型是class A * ,*a的类型是class B
9.基类中存在虚函数,子类就会覆盖基类中和子类同名的虚函数,子类的内存布局
10.基类无虚函数,子类有虚函数。将基类指针指向子类的对象时,其指向子类对象中基类起始的部分。
11.基类定义虚函数和普通重载函数,子类定义同名函数隐藏普通函数
class Base
{
public:
//这两个函数构成重载
void show()
{
cout << "Base::void show()" << endl;
}
virtual void show(int i)
{
cout << "virtual void show(int i )" << endl;
}
};
class Derive :public Base
{
//隐藏父类中的void show函数
public:
void show()
{
cout << "Derive::void show()" << endl;
}
};
int main()
{
Base *base = new Base();
Derive *derive = new Derive();
base->show();
base->show(10);
derive->show();
derive->Base::show();
return 0;
}
12
.基类指针指向堆上的子类对象,此时delete指针,子类析构函数未调用,有可能造成内存泄漏。基类析构函数应该写成虚函数
13.基类构造清除所有数据,基类指针调用自己的虚函数,子类调用虚函数
class Base
{
public:
Base()
{
memset(this, 0, sizeof(Base));
}
virtual void show()
{
cout << "virtual void show()" << endl;
}
};
class Derive :public Base
{
public:
Derive()
:Base()
{
}
void show()
{
cout << "Derive::void show()" << endl;
}
};
int main()
{
Base *base = new Base();
//base->show(); error
Derive *derive = new Derive();
derive->show();
return 0;
}
基类的对象在调用show函数的时候会执行出错,当基类构造的时候将空间内所有字节都置为0,包括vfptr,当访问虚函数的时候就会进入地址位0的空间,访问出错;子类对象在调用show函数的时候会正常执行,虽然基类构造的时候将空间内所有字节包括vfptr都置为0,但是子类在构造的时候将vfptr又置为自己的show函数入口地址,因此访问正常
14.基类和派生类的构造函数、析构函数中调用虚函数不会产生多态调用。因为对象不完整,只要在构造函数之后到析构函数之前对象才是完整的。
15.基类虚函数放到共有,派生类虚函数放到私有,外部基类指针指向子类对象,能否派生类私有函数访问?
可以,该指针是基类的指针,但是又指向子类的示例,在调用之前无法确定调用的究竟是谁
16.基类和子类给不同的虚函数传参数默认值,定义基类指针指向子类对象,调用函数,此时会调用子类的函数,但是函数的参数默认值是基类的参数默认值。
class Base
{
public:
virtual void show(int a= 20)
{
cout <<a << "0000000000000000000"<< endl;
}
};
class Derive :public Base
{
public:
void show(int a = 30000)
{
cout << a << endl;
}
};
int main()
{
Base *base = new Derive();
base->show();
return 0;
}