1. 基类和子类的构造函数与析构函数
创建派生类对象,先调用基类的构造函数,后调用子类的构造函数。
销毁派生类对象,先调用派生类的析构函数,后调用子类的析构函数。
(首先调用基类的构造函数,其次调用成员对象的构造函数),构造函数的调用顺序完全不受初始化列表的影响,由成员对象在类中声明的次序决定的。
class X
{
public:
X(){
cout<<"new X"<<endl;
}
~X(){
cout<<"delete X"<<endl;
}
private:
};
class Y :public X
{
public:
Y(){
cout<<"new Y"<<endl;
}
~Y(){
cout<<"delete Y"<<endl;
}
};
int main()
{
Y y1;
}
new X
new Y
delete Y
delete X
2. 重定义和重写
如果继承了一个类,并且对它的成员函数进行重新定义和重写。
重定义: 和基类一样,明确定义操作和返回类型,非虚函数。
派生类可以和基类一样的 函数名称、参数列表、返回值。 也可以修改参数列表和返回值。
(任何时候,重新定义了基类中的一个重载函数,在新类之中,所有的其他版本都会被隐藏)。
重新定义参数列表和返回类型,实际改变了基类的接口,无需维护基类的接口。
class X
{
public:
X(){
cout<<"new X"<<endl;
}
~X(){
cout<<"delete X"<<endl;
}
int print()
{
cout<<"print X"<<endl;
}
private:
};
class Y :public X
{
public:
Y(){
cout<<"new Y"<<endl;
}
~Y(){
cout<<"delete Y"<<endl;
}
int print()
{
cout<<"print Y"<<endl;
}
};
int main()
{
X* y1 =new Y;
y1->print();
static_cast<Y *>(y1)->print();
}
基类指针->派生类对象 只能调用基类的方法。
派生类指针->派生类对象,只能调用派生类的方法。
(编译时,多态,运行时多态)
重写 :如果基类的函数是虚函数的话,又可以被定义为重写。
3. 非自动继承的函数:
构造函数:
析构函数:
operation =
如果派生类不自己实现,就会
4. 继承和静态函数
静态函数和非静态函数的共同点
(1)它们均可以被继承到派生类对象中去。
(2)我们重新定义了一个静态成员,所有基类中的其他重载函数都会被隐藏。
(3)如果我们改变了基类中的一个函数特征,所有使用该函数名字的基类版本都会被隐藏。
5. private、protected、public
private继承:
私有继承会将基类所有的public 成员公有化。
class X
{
public:
int add(int a,int b);
double add(double a,double b);
int dec(int a,int b);
};
class Y:private X
{
public:
using X::add;//可以使所有的add 函数变成public
private:
};
protected:成员变量
private成员是严格的不能被访问,但实际项目中,有时候希望有些东西被隐藏起来,但它的派生类可以访问。
protected:继承 不常用,只是用于语言的完整性。
6. 向上类型转化:
派生类的指针和引用指向派生类对象,被称为向上类型转换。
向上类型转换总是安全的,但会损失对象的类型信息。
7. 拷贝构造函数
#include<iostream>
#include<vector>
#include<map>
#include<list>
using namespace std;
class Base
{
int value;
public:
Base(){
value= 0;
cout<<"Construct Base"<<endl;
}
Base(int i):value(i)
{
cout<<"Construct Base"<<endl;
}
Base(Base& b):value(b.value)
{
cout<<"Copy Construct Base"<<endl;
}
~Base()
{
cout<<"destory Base"<<endl;
}
};
class Member
{
public:
Member(){
cout<<"Construct Member"<<endl;
}
Member(Member& m){
cout<<"Copy Construct Base"<<endl;
}
~Member(){
cout<<"Destory Member"<<endl;
}
};
class Driv:public Base
{
public:
Member m;
Driv(){
cout<<"Copy Construct Base"<<endl
}
Driv(Driv&c):Base(c)
{
cout<<"copy Driv"<<endl;
}
};
int main()
{
}
如果派生类使用默认拷贝构造函数, 编译器会调用Parent和Member的拷贝函数来生成构造函数。
必须记住的一点:无论我们什么时候创建派生类的拷贝构造函数,必须调用基类的拷贝构造函数。
8.继承和组合的优点是什么?
我们可以从一个类继承,就可以从多个类继承,我们很好的学会了程序设计,就可以理解它。
继承和组合的优点是支持渐增式开发。
它允许在已经存在的代码带来错误,即使产生了错误,这种错误的代码也只与新代码有关系。
如何确定使用引用或者是继承:
是否需要新类向上类型转换。