一、继承
介绍:
继承就是子类可以通过继承获得父类当中数据成员和成员函数,继承只可以获得父类当中的public公有权限和portected保护权限的数据成员和成员函数,继承不能继承父类的构造函数和析构函数。
使用:
用于类与类之间,通过继承机制,可以利用已有的数据类型来定义新的数据类型,所定义的新的数据不仅拥有新定义的成员,还有继承来的成员。
已存在的用来派生其他类的类叫基类或父类,由已存在的类派生出来的类叫派生类或者子类。
步骤:
1、吸收基类成员
2、覆盖类同名成员
3、添加新成员
注意:析构、构造函数不能继承
派生类的定义:
单继承:只有一个父类
单继承格式:
class 派生类名: 继承方式 基类名 //派生类名自定义,继承方式有private,portected,public,使用public即可,基类名则是派生类需要继承的父类的类名
{
};
继承方式:将基类看做子类的成员,当子类创建对象时,以何种权限实现对其成员的访问。
public:基类公有public成员和保护portected成员保持原有的状态,私有成员private不能在派生类中访问
private:基类公有public成员和保护portected成员都作为派生类的私有成员
protected:基类公有public成员和保护portected成员都作为派生类的保护成员
通常为public
例子:point和point3D --- 单继承
#include<iostream>
using namespace std;
class point
{
private:
int xp;
int yp;
public:
point(int x = 0,int y = 0)
{
xp = x;
yp = y;
}
void show()
{
cout << "继承" << endl;
}
protected:
void setxp(int x)
{
xp = x;
}
int getxp(void)
{
return xp;
}
void setyp(int y)
{
yp = y;
}
int getyp(void)
{
return yp;
}
};
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;
}
protected:
void setzp(int z)
{
zp = z;
}
int getzp(void)
{
return zp;
}
};
int main()
{
point3D a(1,2,3);
a.show();
return 0;
}
注意:在子类初始化的时候自动调用父类的构造函数只能用初始化表达式的形式
设计类的时候一般属性可以设置private,protected,public,但是一般成员函数设置成public
多继承
多继承定义格式:
class 派生类名:继承方式 基类名,继承方式 基类名......
{
};
多继承可能会遇到的问题:
1、多继承二义性 --- 函数名冲突 --- 调用的时候 加 类名::指定是哪一个类型里面的成员函数
2、共基类 --- 多个共基类型拷贝 --- 加 类名:: 或虚继承
多继承二义性例子:
#include<iostream>
using namespace std;
// A -- 父类
class A
{
public:
int ax;
A(int x=0)
{
ax = x;
}
void printA()
{
cout << "ax:" << ax << endl;
}
void show()
{
cout << "我是Ashow" << endl;
}
};
// B -- 父类
class B
{
public:
int bx;
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.ax = 100;
obj.printA();
// obj.show(); 报错:有歧义,不知道执行继承哪一个
obj.A::show();
return 0;
}
虚继承解决共基类的二义性问题例子:
#include<iostream>
using namespace std;
class D
{
public:
int a;
void show()
{
cout << "我是基类Dshow" << 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;
}
区分继承和组合
继承:由学生类继承人类类,老师类继承人类类
组合:人类由鼻子类,眼睛类,嘴巴类,耳朵类,眉毛类组成五官,只相关不继承
类型适应
派生类使用于基类,派生类的对象、指针、引用适用于基类对象、指针、引用
基类的对象、指针、引用 = 子类的对象、指针、引用赋值
#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();
// 基类的引用 引用子类的对象
A &k = b;
k.show();
return 0;
}