继承与派生---day4
1、基本概念
继承:将旧的内容保留下来,变成新的内容的一部分;
派生:在旧的内容的基础,添加进新的内容;
基类:已经存在的类成为基类或父类。
派生:新建立的类成为派生类或者子类。
2、单一继承
格式:class 派生类名:<继承方式> 基类名
继承方式:public(公有派生)/protected(保护派生)/private(私有派生) ----默认的是私有派生
#include<iosteram>
#include<string>
using namespace std;
class student
{
private:
int num;
char name[20];
char sex;
public:
void dispay();
};
class student1:public student //声明基类是student,公有派生
{
private:
int age;
char addr[20];
public:
void dispaly_1();
};
void student::dispay()
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
cout<<"sex:"<<sex<<endl;
}
void student1::dispaly_1()
{
cout<<"age:"<<age<<endl;
cout<<"address:"<<addr<<endl;
}一个派生类可以从一个基类派生,也可以从多个基类中派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。
1)当定义了一个类,这个类只能用作基类来派生出新的类,而不能用作这种累来定义对象时,称这种类为抽象类。当某些特殊的对象要进行很好地封装时,需要定义抽象类。
将类的构造函数或析构函数的访问权限定义为保护的时候,这种类为抽象类。
2)当把类中的构造函数或析构函数说明为私有的时,所定义的类通常是没有任何实用意义,一般情况下,不能用它来产生对象,也不能用来产生派生类。
#include<iostream>
using namespace std;
class A
{
int x,y;
protected:
A(int a,int b)
{
x=a;
y=b;
}
public:
void showA()
{
cout<<"x= "<<x<<endl;
cout<<"y= "<<y<<endl;
}
};
class B:public A
{
int z;
//A a1;//在派生类中不可以定义A的对象,实际上是类外调用
public:
B(int a,int b,int c):A(a,b)//可以在派生类中调用A的构造函数,通过初始化成员列表的形式可以
{
// A.x=a; //不可以在函数体内调用基类的私有成员进行操作
// A.y=b;
z=c;
};
void show()
{
cout<<"z="<<z<<endl;
showA(); //可以调用基类的普通成员函数(基类中是公有的)
}
};
int main()
{
B b1(1,3,5);
b1.show();
// A a1; //不可以定义类A的对象
return 0;
}
3、多重继承:可以用多个基类来派生出一个类
格式:class 类名:<继承方式>类名1,...,<继承方式>类名n
{
private:.......;//私有成员说明
public:........;//公有成员说明
protected:......;//保护的成员说明
};
class D: public A, protected B, private C {
....//派生类中新增加成员};
3、1如何初始化基类成员
构造函数不能被继承,派生类的构造函数必须调用基类的构造函数来初始化基类成员及,基类子对象。
派生类构造函数的调用顺序如下:
1)基类的构造函数
2)子对象类构造函数
3)派生类的构造函数
注意:当派生类中新增加的数据或函数与基类中原有的同名时,若不加限制,则优先调用派生类中的成员。
4、基类与对象成员任一基类在派生类中只能继承一次,否则,会造成成员名的冲突 ;
若在派生类中,确实要有二个以上基类的成员,则可用基类的二个对象作为派生类的成员。
把一个类作为派生类的基类或把一个类的对象作为一个类的成员,在使用上是有区别的:在派生类中可直接使用基类的成员(访问权限允许的话),但要使用对象成员的成员时,必须在对象名后加上成员运算符“.”和成员名。
5、虚基类
在多重派生的过程中,若使公共基类在派生类中只有一个拷贝,则可将这种基类说明为虚基类。
在派生类的定义中,只要在基类的类名前加上关键字virtual,就可以将基类说明为虚基类。
格式:class B:public virtual A
{
public:......
int y;
}
说明:由虚基类派生出的对象初始化时,直接调用虚基类的构造函数。因此,若将一个类定义为虚基类,则一定有正确的构造函数可供所有派生类调用。
5、拷贝构造函数
#include <iostream>
#include<string>
using namespace std;
class student
{
string name;
int age;
string sex;
public:
//构造函数
student(string n,int a,string s)
{
name = n;
age = a;
sex = s;
}
void display_stu()
{
cout<<"name :"<<name<<endl;
cout<<"age :"<<age<<endl;
cout<<"sex :"<<sex<<endl;
cout<<endl;
}
student(student &s) //拷贝构造函数
{
name = s.name;
age = s.age+2;
sex = s.sex;
}
};
class cpstudent:public student
{
string addr;
int number;
public:
cpstudent(string n,int a,string s,string add,int num):student(n,a,s)
{
addr = add;
number = num;
}
void dispaly_cpstu()
{
display_stu();
cout<<"addr :"<<addr<<endl;
cout<<"num :"<<number<<endl;
}
//在派生类中实现基类的拷贝是通过构造函数初始化类别,而传入的参数是传入派生类的地址找到基类地址实现拷贝功能
cpstudent(cpstudent &cps):student(cps)
{
addr = cps.addr;
number = cps.number;
}
};
int main()
{
cpstudent stu("lily",23,"女","中路10号",13624678);
stu.dispaly_cpstu();
cout<<"\n"<<endl;
cpstudent stu1 = stu; //拷贝构造操作
stu1.dispaly_cpstu();
return 0;
}在主函数中实现拷贝构造函数的操作,必须在类中定义拷贝构造函数。