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