【单继承】
继承性是面向对象程序设计中最重要的机制。这种机制提供了无限重复利用程序资源的一种途径。通过C++语言中的继承机制,可以扩充和完善旧的程序设计以适应新的需求。这样不仅可以节省程序开发的时间和资源,并且为未来程序增添了新的资源。
class Student //类Student
{ int num;
char name[30];
char sex;
public:
void display( ) // 对成员函数display的定义
{
cout <<"num: " <<num <<endl;
cout <<"name: " <<name <<endl;
cout <<"sex: " <<sex <<endl;
}
};
class Student1 //类Student1
{ int num;
char name[20];
char sex;
int age; //新增的
char addr[20]; //新增的
public:
void display( )
{
cout <<"num: " <<num <<endl;
cout <<"name: " <<name <<endl;
cout <<"sex: " <<sex <<endl;
cout <<"age: " <<age <<endl; //新增的
cout <<"address: " <<addr <<endl; //新增的
}
};
利用原来定义的类Student作为基础,再加上新的内容即可,以减少重复的工作量。 C++提供的继承机制就是为了解决这个问题。
在C++中所谓“继承”就是在一个已存在的类的基础上建立一个新的类。已存在的类称为“基类(base class)”或“父类(father class)”。新建立的类称为“派生类(derived class)”或“子类(son class)”。
class Student1: public Student//声明基类是Student,定义派生类Student1
{
private:
int age; //新增加的数据成员
string addr; //新增加的数据成员
public:
void display_1( ) //新增加的成员函数
{
cout<<"age: "<<age<<endl;
cout<<"address: "<<addr<<endl;
}
};
类A派生类B:类A为基类,类B为派生类。
在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。
通过继承机制,可以利用已有的数据类型来定义新的数据类型。所定义的新的数据类型不仅拥有新定义的成员,而且还同时拥有旧的成员。我们称已存在的用来派生新类的类为基类,又称为父类。由已存在的类派生出的新类称为派生类,又称为子类。
在建立派生类的过程中,基类不会做任何改变,派生类则除了继承基类的所有可引用的成员变量和成员函数外,还可另外定义本身的成员变量和处理这些变量的函数,由于派生类可继承基类的成员变量和成员函数,因此在基类中定义好的数据和函数等的程序代码可重复使用,这样可以提高程序的可靠性。
当从已有的类中派生出新的类时,可以对派生类做以下几种变化:
1、可以继承基类的成员数据或成员函数。
2、可以增加新的成员变量。
3、可以增加新的成员函数。
4、可以重新定义已有的成员函数。
5、可以改变现有的成员属性。
在C++中有二种继承:单一继承和多重继承。当一个派生类仅由一个基类派生时,称为单一继承;而当一个派生类由二个或更多个基类所派生时,称为多重继承。
但派生并不是简单的扩充,有可能改变基类的性质。 有三种派生方式:公有派生、保护派生、私有派生。 默认的是私有派生。
从一个基类派生一个类的一般格式为:
class ClassName: <Access> BaseClassName // 派生类名:继承方式 基类名
{
private: // 派生类中新增加的成员
......; //私有成员说明
public:
......; //公有成员说明
protected:
......; //保护成员说明
};
1、【公有派生】
class ClassName : public BaseClassName
公有派生时,基类中所有成员在派生类中保持各个成员的访问权限。
基类:public: 在派生类和类外可以使用
protected: 在派生类中使用
private: 不能在派生类中使用
例:
// 单继承
#include <iostream>
using namespace std;
class A
{
private:
int x; //私有数据成员
public:
int z; //公有数据成员
A(int a, int b, int c)
{
cout << " 调用类A 带参的构造函数" << endl;
x = a;
y = b;
z = c;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
void disp()
{
cout << " x=" << x << ", y=" << y << " , z=" << z << endl << endl;
}
protected:
int y; //保护数据成员
};
class B : public A //公有派生
{
private:
int m, n; //私有数据成员
public:
B(int a, int b, int c, int d, int e) :A(a, b, c)
{
cout << " 调用派生类B 带参的构造函数" << endl;
m = d;
n = e;
}
void disp()
{
cout << " x=" << getx(); //x在派生类B新增加的成员中不能直接调用
cout << ", y=" << y << " , z=" << z; //y在类B中可以调用, z在整个文件中可以调用
cout << ", m=" << m << " , n=" << n << endl << endl;
}
int sum()
{
return (getx()+y+z+m+n);
}
};
int main()
{
B test(1, 2, 3, 4, 5);//派生类B 创造对象test,且初始化参数1 2 3 4 5
test.disp();
cout << " sum = " << test.sum() << endl;
cout << " x= " << test.getx() << endl; // 类A 公有函数可在外调用
cout << " y= " << test.gety() << endl;
return 0;
}
输出结果:
2、【私有派生】
class ClassName: private BaseClassName
私有派生时,基类中公有成员和保护成员在派生类中均变为私有的,在派生类中仍可直接使用这些成员; 基类中的私有成员,在派生类中不可直接使用。
基类: public: (变为私有)在派生类中使用,类外不可使用
protected: (变为私有)在派生类中使用,类外不可使用
private: 不能在派生类中和类外使用
例:
// 单继承
#include <iostream>
using namespace std;
class A
{
private:
int x; //私有数据成员
public:
int z; //公有数据成员
A(int a, int b, int c)
{
cout << " 调用类A 带参的构造函数" << endl;
x = a;
y = b;
z = c;
}
int getx()
{
return x;
}
int gety()
{
return y;
}
void disp()
{
cout << " x=" << x << ", y=" << y << " , z=" << z << endl << endl;
}
protected:
int y; //保护数据成员
};
class B : private A //私有派生
{
private:
int m, n; //私有数据成员
public:
B(int a, int b, int c, int d, int e) :A(a, b, c)
{
cout << " 调用派生类B 带参的构造函数" << endl;
m = d;
n = e;
}
void disp()
{
cout << " x=" << getx(); //x在派生类B新增加的成员中不能直接调用
cout << ", y=" << y << " , z=" << z; //y、z 在派生类B中可以调用
cout << ", m=" << m << " , n=" << n << endl << endl;
}
int sum()
{
return (getx()+y+z+m+n);
}
};
int main()
{
B test(1, 2, 3, 4, 5);//派生类B 创造对象test,且初始化参数1 2 3 4 5
test.disp();
cout << " sum = " << test.sum() << endl;
//cout << " x= " << test.getx() << endl; // 类A公有函数不能可在外调用
//cout << " y= " << test.gety() << endl;
return 0;
}
输出结果:
3、【保护派生】
class ClassName: protected BaseClassName
保护派生时,基类中公有成员和保护成员在派生类中均变为保护的和私有的,在派生类中仍可直接使用这些成员; 基类中的私有成员,在派生类中不可直接使用。
基类: public: (变为保护)在派生类中使用,类外不可使用
protected: (变为私有)在派生类中使用,类外不可使用
private: 不能在派生类中和类外使用
protected 成员是一种具有血缘关系内外有别的成员。它对派生类的对象而言,是公开成员,可以访问,对血缘外部而言,与私有成员一样被隐蔽。
4、【抽象类与保护的成员函数】
当定义了一个类,这个类只能用作基类来派生出新的类,而不能用这种类来定义对象时,称这种类为抽象类。当对某些特殊的对象要进行很好地封装时,需要定义抽象类。
将类的构造函数或析构函数的访问权限定义为保护的时,这种类为抽象类。
当把类中的构造函数或析构函数说明为私有的时,所定义的类通常是没有任何实用意义的,一般情况下,不能用它来产生对象,也不能用它来产生派生类。
在类B中不能定义A的对象;
在任何时候都不能定义A的对象;
但可以在初始化类B的对象时初始化原类A中的成员,因为A()在类B中是可以被调用的。
例:
#include <iostream>
using namespace std;
class A //将类的构造函数或析构函数的访问权限定义为保护的时,这种类为抽象类
{
protected:
A(int a, int b) //基类初始化, 类的构造函数的访问权限定义为保护的时
{
cout << " 调用类A 带参的构造函数" << endl;
x = a;
y = b;
}
public:
int x, y;
};
class B : public A
{
private:
int m; //私有数据成员
//A test; //在派生类中也不可以定义类A的对象,实际上还是类外调用
public:
B(int a, int b, int c) :A(a, b)//可以在派生类调用 类A的构造函数
{
cout << " 调用派生类B 带参的构造函数" << endl;
m = c;
}
void disxy()
{
cout << " x=" << x << ", y=" << y << ", m=" << m << endl << endl;
}
};
int main()
{
B test(1, 2, 3);//可以定义派生类对象test,且初始化参数1 2 3
test.disxy();
return 0;
}
输出结果: