提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一.概念:
类的继承:一个新类从已有的类那里获得已有的特征。
类的派生:从已有的类(父类)产生一个新的子类。
最简单的示例:
class Student
{
public:
void display()
{
cout<<"num:"<<num<<endl;
}
private:
int num;
};
重新声明另一个类
class Student
{
public:
void display()
{
cout<<"num:"<<num<<endl;//此行原来已有
cout<<"name:"<<name<<endl;
}
private:
int num;//此行原来已有
int name;
};
派生类是基类的具体化,而基类则是派生类的抽象。
二.派生类的声明方式
class 派生类名:【继承方式】 基类名
{
派生类新增的成员;
};
示例:根据根据前面已经声明的Student类基础上
单继承建立一个派生类Student1
class Student1:public Student
{public:
void display_1()
{cout<<"name:"<<name<<endl;}
private:
int name;
};
继承方式:public(公用的),private(私有的),protected(受保护的)。不写此项默认为private。具体在后面会阐述。
三.派生类的构成
- 从基类接收成员。派生类把基类的全部成员(不包括构造函数和析构函数)接收过来,没有选择权。
- 调整从基类接收的成员。可以声明一个与基类成员同名的成员,就会覆盖同名成员。用这种方法可以用新成员取代基类的成员。
- 在声明派生类时增加的成员。
四.派生类成员的访问属性
公用继承public
继承方式为public。基类的公有成员和保护成员在派生类中保持原有的访问属性,其私有成员仍为基类所有,为派生类的不可访问成员。
只能通过基类的公用成员函数来引用基类的私有数据成员
私有继承private
基类的公有成员和保护成员在派生类中成了私有成员。私有基类的私有成员在派生类中成为不可访问成员。
保护成员和保护继承protected
保护基类的公有成员和保护成员在派生类都成了保护成员,私有成员依然为基类私有。
保护成员不能被类外访问,与私有成员相似,但是保护成员可以被派生类的成员函数引用。
- 多级派生时的访问属性
示例:A类是基类,类B是类A的派生类,类C是B类的派生类,则类C也是类A的派生类。B称为A的直接派生类,C是A的间接派生类。
在多级派生的情况下,各成员的访问属性仍按以上原则确定。
五.派生类的构造函数和析构函数
(1)简单的派生类构造函数
派生类构造函数 一般形式:
派生类构造函数名(总参数表):基类构造函数名(参数表)
{派生类中新增数据成员初始化语句}
示例:定义构造派生类
public:
Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)
//因为在这里不是定义基类构造函数,而是调用基类构造函数,
//因此这些参数是实参而不是形参
{age=a;//在函数体中只对派生类新增的数据成员初始化
addr=ad;}
也可以改成一下方式:
Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s),agg(a),addr(a){}
注:在函数体中只对派生类新增的数据成员初始化
(2)有子对象的派生类构造函数
一般形式:派生类构造函数名(总参数表):基类构造名(参数表),子对象名(参数表){派生类中新增数据成员初始化表}
示例:包含子对象的派生类的构造函数
(monitor班长是基类Student的对象,也是派生类Student1的子对象)
#include<iostream>
#include<cstring>
using namespace std;
class Student
{
public:
Student(int n,string nam)//基类构造函数
{num=n;name=nam;}
void display()//成员函数,输出基类数据成员
{cout<<"num:"<<num<<endl<<"name:"<<name<<endl;}
private:
int num;
string name;
} ;
class Student1:public Student//声明公用派生类Students1
{
public:
Student1(int n,string nam,int n1,string nam1,int a,string ad)
:Student(n,nam),monitor(n1,nam1)//派生类构造函数
{
age=a;addr=a;
}
void show()
{
cout<<"this student is"<<endl;
display();
cout<<"age"<<age<<endl;
cout<<"address"<<addr<<endl;
}
void show_monitor()
{
cout<<endl<<"class monitor is"<<endl;
monitor.display();//调用基类成员函数
}
private:
Student monitor;//定义子对象(班长)
int age;
string addr;
};
int main()
{
Student1 stud1(10010,"wang",10011,"li",19,"beingjing");
stud1.show();//输出学生数据
stud1.show_monitor() ;//输出子对象数据
return 0;
}
(3)多层派生时的构造函数**
基类构造函数首部:
student(int n,string nam)
派生类student1的构造函数首部:
student(int n,string nam,int a):studen(n,nam)
派生类student2的构造函数首部:
student(int n,string nam,int a,int s):student1(n,nam,a)
注:每一层派生类只需要写出上一层派生类的构造函数即可。
- (4)派生类构造函数的特殊形式
当不需要对派生类新增成员进行任何操作时,函数体可以为空,即构造函数是空的。
示例:将上面的代码改写
student1(int n,string nam,int n1,string nam1)
:student(n,nam),monitor(n1,nam1){}
六.多重继承
多重继承:允许一个派生类同时继承多个基类
(1)声明多重继承的方法
classD:public A,private B,protected C
{类D新增加的成员}
(2)多重继承派生类的构造函数**
派生类构造函数名(总参数表):基类1构造函数(参数表),基类2构造函数(参数表),基类3构造函数(参数表列)
{派生类中新增数据成员初始化语句}
(3)虚基类
使得在继承间接共同基类时只保留一份成员。避免产生二义性(多重继承引起的),使其唯一地标识一个成员。
一般形式:class 派生类名:virtual 继承方式 基类名
class A{...};
class B:virtual public A{...};//声明类B是类A的公用派生类,A是B的虚基类
虚基类的初始化
class A//定义基类A
{A(int i){}...};//基类构造函数,有一个参数
class B:virtual public A//A作为B的虚基类
{B(int n):A(n){}...};//B类构造函数,在初始化表中对虚基类初始化
class C:virtual public A
{C(int n):A(n){}...};
class D:public B,public C//D类构造函数,在 初始化表中对所有基类初始化
{D(int n):A(n),B(n),C(n){}...};
注:在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。
七.基类与派生类的转换
基类与派生类对象之间有赋值兼容性。
--------即可以用子类(公用派生类)对象对其基类对象赋值
示例:
A a1;//定义基类A对象a1
B b1;//定义类A的公用派生类B的对象b1
a1=b1;
注:(1)只能用子类对象对其基类对象赋值,同一基类的不同派生类对象之间也不能赋值。
(2)派生类对象可以替代基类对象向基类对象的引用进行赋值或初始化。
(3)如果函数的参数是基类对象或基类对象的引用,相应的实参可以用子类对象。
(4)指向基类对象的指针变量也可以指向派生类对象。
ps:详情有空再加一点。。。。。