第一部分 类的继承与派生
1.1继承的概念
类的继承指的是新的类从已有的类中得到已有的特性;派生指的是已有的类产生新类的过程。
已有的类称为:父类或者基类;
产生的新类称为:派生类或者子类。
继承可以分为单继承和多重继承。
单继承:比如父类学生—>派生类类研究生
多继承:比如父类狮子和父类老虎—>派生类狮虎兽
2.2 派生类的声明
C++中派生类声明的语法:
class 派生类名:继承方式 基类名1,继承方式 基类名2, ……,继承方式 基类名n
{
派生类成员声明;
}
派生类的生成过程:
1. 吸收基类成员,但不包含构造函数和析构函数
2. 改造基类成员,一是通过继承方式来控制,而是隐藏基类成员变量和成员函数,比如在派生类中声明一个与基类成员同名的成员,这时在派生类中或者在派生类对象中使用该成员名,就只能使用派生类中声明的同名成员。
3. 增加新成员
2.3 访问控制
派生类虽然之间继承了基类的全部的数据成员和除了构造函数和析构函数之外的全部的函数成员,但是在派生类中这些成员的访问属性却通过继承方式来控制。
继承方式一空有三种:
2.3.1 共有继承
这种继承方式,基类中的公有成员和保护成员在派生类中仍然是公有成员和保护成员,派生类的成员可以直接访问它,但是基类中的私有成员在派生类中不可访问!
注意:派生类的对象只能访问基类中的公有变量!
示例程序:
#include <iostream>
using namespace std;
class A
{
private:
int x;
protected:
int y;
public:
int z;
void setx(int i)
{
x = i;
}
int getx()
{
return x;
}
};
class B:public A
{
private:
int m;
protected:
int n;
public:
int p;
void setvalue(int a, int b, int c, int d, int e, int f)
{
setx(a);
y = b;
z = c;
m = d;
n = e;
p = f;
}
void display()
{
cout << "x=" <<getx()<< endl;
// cout << "x=" <<x<< endl; 基类中x为私有变量,派生类中成员函数不能直接访问
cout << "y=" << y << endl; //基类中y为保护变量,派生类中成员函数可以直接访问
cout << "m=" << m << endl;
cout << "n=" << n <<endl;
}
};
int main()
{
B obj;
obj.setvalue(1,2,3,4,5,6);
obj.display();
// cout << "y=" << obj.y << endl; 基类中y为保护变量,派生类的对象不可以直接访问
cout << "z=" << obj.z << endl; //基类中z为公有变量,派生类的对象可以直接访问
cout << "p=" << obj.p << endl;
return 0;
}
执行结果:
2.3.2 私有继承
这种方式下,基类中的public何protected成员在派生类中均为private身份出现在派生类中。派生类中的成员函数可以直接访问基类中的public成员和protected成员,但不能访问基类中的private成员!
注意:但是派生类的对象不能直接访问基类中的任何成员!
示例程序:
#include <iostream>
using namespace std;
class A
{
private:
int x;
protected:
int y;
public:
int z;
void setx(int i)
{
x = i;
}
int getx()
{
return x;
}
class B:private A
{
private:
int m;
protected:
int n;
public:
int p;
void setvalue(int a, int b, int c, int d, int e, int f)
{
setx(a);
y = b;
z = c;
m = d;
n = e;
p = f;
}
void display()
{
cout << "x=" <<getx()<< endl;
// cout << "x=" <<x<< endl; 基类中x为私有变量,派生类中成员函数不能直接访问
cout << "y=" << y << endl; //基类中y为保护变量,派生类中变为私有变量,派生类中成员函数可以直接访问
cout << "m=" << m << endl;
cout << "n=" << n <<endl;
}
};
int main()
{
B obj;
obj.setvalue(1,2,3,4,5,6);
obj.display();
// cout << "y=" << obj.y << endl; 基类中y为保护变量,派生类的对象不可以直接访问
// cout << "z=" << obj.z << endl; //在通过继承变为私有成员,派生类的对象不可以直接访问
cout << "p=" << obj.p << endl;
return 0;
}
执行结果:
2.3.3 保护继承
这种方式下基类中的public和protected成员都以protected的方式出现在派生类中,派生类中的成员函数可以直接访问基类中的public和protected成员,但是不能直接访问基类中的private成员。注意:派生类中的对象不能访问基类中的任何成员!
保护继承与私有继承的差别主要体现在当前派生类进一步派生的子类中,而在当前派生类这一层次上,保护继承与私有继承没有差别!
比如:Circle私有继承了Point类,而Circle作为新的基类又派生出了Cylinder类,那么Cylinder的类和对象都不能够访问Circle从Point类继承来的任何成员。
如果Circle是以保护方式继承了Point类,那么当Circle类再派生处Cylinder类时,Point类中的Public和Protected成员都会被Cylinder类继承为保护形式或者私有形式,但具体要看Cylinder对Circle的继承方式!
2.4 类型兼容规则
指的是公有派生类继承了基类中除构造函数和析构函数之外的所有成员,这样凡是需要用基类对象的地方,都可以用公有对象来替代!
类型兼容规则中所指的替代报告以下几种情况:
1. 派生类的对象可以赋值给基类的对象
2. 派生类的对象可以初始化基类的引用
3. 派生类对象的地址可以赋值给指向基类的指针
注意:在替代之后,派生类的对象就可以作为基类的对象使用,但是只能使用从基类继承的成员!(后面介绍的虚函数可以改变这种状况,即可以访问派生类中和基类同名的成员函数)
示例代码:
#include <iostream>
using namespace std;
class pet
{
public:
void speak()
{
cout << "How does a pet speak!" << endl;
}
};
class cat:public pet
{
public:
void speak()
{
cout << "miao ! miao!" << endl;
}
};
class dog:public pet
{
public:
void speak()
{
cout << "wang! wang!" << endl;
}
};
int main()
{
pet *p1, *p2, *p3, obj;
dog dog1;
cat cat1;
obj = dog1; //派生类的对象可以复制给基类对象
obj.speak(); //派生类作为基类使用,只能使用基类里成员函数
p1 = &cat1; //派生类的对象的地址可以复制给基类对象指针
p1->speak();//派生类对象作为基类使用,只能使用基类里的成员函数
p1 = &dog1;//派生类的对象的地址可以复制给基类对象指针
p1->speak();//派生类的对象的地址可以复制给基类对象指针
p2 = new cat;
p2->speak();//派生类对象作为基类使用,只能使用基类里的成员函数
p3 = new dog;//派生类的对象的地址可以复制给基类对象指针
p3->speak();//派生类对象作为基类使用,只能使用基类里的成员函数
pet &p4 = cat1; //派生类对象可以初始化基类的引用
p4.speak();//派生类对象作为基类使用,只能使用基类里的成员函数
dog1.speak();
cat1.speak();
return 0;
}
指向结果: