继承概念
继承:是发生在类与类之间,通过继承机制,可以利用已有的数据类型来定义新的数据类型,所定义的新的数据不仅拥有新定义的成员,还有继承来的成员。
已存在用来派生其他类的类叫基类或父类,由已存在的类派生出来的类叫派生类或者子类。
目的:类复用,提高效率,缩短开发周期。
继承的分类:单继承 、 多继承
继承的实现步骤:
1、吸收基类成员
2、覆盖基类同名成员
3、添加新成员
注意:析构、构造函数不能继承
继承的定义
单继承
只有一个基类,定义格式:
class 派生类名:继承方式 基类名
{
// 新成员
};
继承方式有三种:
public:基类公有成员和保护成员保持原有的状态,私有不能在派生类中访问
private:基类公有成员和保护成员都作为派生类的私有成员
protected:基类公有成员和保护成员都作为派生类的保护成员
一般使用public
例如:
#include<iostream>
using namespace std;
// Point -- 基类
class Point
{
private:
int xp;
int yp;
public:
Point(int x=0,int y=0)
{
xp = x;
yp = y;
}
int getXP(void)
{
return xp;
}
int getYP(void)
{
return yp;
}
};
// Point3D -- 子类
class Point3D:public Point
{
private:
int zp;
public:
Point3D(int x=0,int y=0,int z=0):Point(x,y) //子类初始化调用了基类构造函数
{
zp = z;
}
void show()
{
cout << "xp" << getXP() << ",yp" << getYP() << ",zp" << zp << endl;
}
};
int main()
{
Point3D a(1,2,3);
a.show();
return 0;
}
子类继承过来的成员在使用时必须要使用初始化的形式
多继承
多继承定义格式:
class 派生类名:继承方式 基类名,继承方式 基类名.......
{
};
多继承中的注意事项:
1、多继承可能会出现不同类中继承过来的函数命名冲突,可以在调用的时候在函数前加 “类名::” 指定是哪一个类里面的成员函数
例:
#include<iostream>
using namespace std;
// A -- 基类
class A
{
private:
int ax;
public:
A(int x=0)
{
ax = x;
}
void printA()
{
cout << "ax:" << ax << endl;
}
void show()
{
cout << "我是Ashow" << endl;
}
};
// B -- 父类
class B
{
private:
int bx;
public:
B(int x=0)
{
bx = x;
}
void printB()
{
cout << "bx:" << bx << endl;
}
void show()
{
cout << "我是Bshow" << endl;
}
};
class C:public A,public B
{
public:
C(int x,int y):A(x),B(y)
{
}
};
int main()
{
C obj(1,5);
obj.printA();
obj.printB();
// obj.show(); 报错:有歧义,不知道执行继承哪一个
obj.A::show();
return 0;
}
2、多继承如果出现了多个共基的类再次继承给新的子类,会出现多次复制内容,通过虚继承virtual关键字解决
#include<iostream>
using namespace std;
class D
{
public:
int a;
void show()
{
cout << "基类D的函数" << endl;
}
};
class A:virtual public D
{
};
class B:virtual public D
{
};
class C:public A,public B
{
};
int main()
{
C obj;
obj.show();
return 0;
}
虚继承:使共同基类只产生一个拷贝,只对第一个调用有效,对其他派生类都是虚假的,没有调用构造函数。
继承中构造函数和析构函数的执行顺序
构造函数和析构函数是不能继承的,子类只能自己使用自己的构造函数和析构函数
调用基类的构造函数必须在派生类的构造函数中使用初始化表达式的形式
构造函数执行顺序:先基类再派生类
析构函数执行顺序:先派生类再基类
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout << " 基类 构造函数" << endl;
}
~A()
{
cout << " 基类 析构函数" << endl;
}
};
class B:public A
{
public:
B()
{
cout << " 子类 构造函数" << endl;
}
~B()
{
cout << " 子类 析构函数" << endl;
}
};
int main()
{
B obj;
return 0;
}
运行分4步, 1基类构造函数 2子类构造函数 3子类析构函数 4基类析构函数
类型适应
子类对象可以赋值给基类对象,基类指针可以指向子类,基类对象可以引用子类对象。反过来不行
#include<iostream>
using namespace std;
class A
{
public:
int xp;
A(int x=0)
{
xp = x;
}
void show()
{
cout << "xp" << xp << endl;
}
};
class B:public A
{
public:
int yp;
B(int x=0,int y=0):A(x)
{
yp = y;
}
void show()
{
cout << "xp:" << xp << ",yp" << yp << endl;
}
};
int main()
{
A a(5);
B b(1,5);
a.show();
b.show();
// 父类的对象 = 子类的对象
a = b;
a.show();
// 使用基类的指针 指向子类对象
A *t = &b;
t->show(); //t指向b,调用的函数是基类A的函数
// 基类的引用 引用子类的对象
A &k = b;
k.show(); //k引用b,调用的函数是基类A的函数
return 0;
}