概念
类之间的有一种层次关系,有父亲类,孩子类.
父亲类:基类,超类
孩子类:子类,派生类
继承:有父亲类,有孩子类,构成了层次关系
(面向对象有三个核心:继承,封装,多态)
继承
这种继承,简单说就是需要先定义一个父类,父类中定义一些公用的成员变量,成员函数,我们通过继承父类来构建新的类,也就是子类;
所以,写代码时,只需要写和子类相关的一些内容即可.
示例
“Human.h”
#ifndef __HUMAN__
#define __HUMAN__
#include <iostream>
using namespace std;
class Human
{
public:
Human();
Human(int);
private:
int m_Age;
char m_Name[100];
};
#endif // !__HUMAN__
“Human.cpp”
#include "Human.h"
Human::Human()
{
cout << "执行了构造函数Human::Human()" <<endl;
}
Human::Human(int)
{
cout << "执行了构造函数Human::Human(int)" << endl;
}
“Man.h”
#ifndef __MEN__
#define __MEN__
#include <iostream>
#include "Human.h"
using namespace std;
class Men : public Human //表示Men是Human的子类
{
public:
Men();
};
#endif
“Man.cpp”
#include "Men.h"
Men::Men()
{
cout << "执行了构造函数Men::Men()" << endl;
}
“Main”
#include "Men.h"
#include <iostream>
int main()
{
Men men; //执行了构造函数Human::Human()
//执行了构造函数Men::Men()
//当定义子类对象时,是要调用父类和子类的构造函数,而且,父类的构造函数的函数体先执行,子类构造函数的函数体后执行
return 0;
}
整个程序的运行结果是先执行父类构造函数的函数体,在执行子类构造函数的函数体;
访问等级
三种访问权限
public: 可以被任意实体访问
protected: 只允许本类或者子类的成员函数访问
private: 只允许本类的成员函数访问
继承方式
从刚才的示例中可以看到,通过public方式继承父类,当然,也可以使用这三种方式.
class Men : public Human
class Men : protected Human
class Men : private Human
子类所能得到的权限:
示例中加入一些测试代码,可以测试一下这些权限,以下是举例:
说明:子类继承方式为public
//"Human.h"
public:
int m_Age;
char m_Name[100];
void funcpub() {};
protected:
int m_pro;
void funcpro() {};
private:
int m_priv;
void funcpriv() {};
int main()
{
Men men;
men.m_Age; //允许,父类public,任意实体访问
men.m_pro; //不允许,protected只允许本类或者子类的成员函数访问\
这里是main函数,显然不行; 可以再Men中的成员函数中访问
men.m_priv; //不允许, 访问权限不够,只允许父类的成员函数*访问
return 0;
}
如果子类继承方式为protected,那么父类public 也要变成protected(子类想要访问只能在成员函数中访问)(详细看表)
函数遮蔽问题
父类函数
//这里是父类 Human
public:
void sameFunc();
void sameFunc(int);
子类函数
//这里是子类 men
public:
void sameFunc(int);
main
//调用测试
Men men;//实例一个子类
men.sameFunc(123); //这里调用了子类的sameFunc(int)函数,而不是父类的
men.sameFunc(); //报错,无法调用父类中的不带参同名函数
范例中可以看出,当子类和父类存在同名成员函数时,通过子类,无法调用父类中的同名函数,因为子类中的函数遮蔽掉了父类中的同名函数.
解决这个问题的方法就是:
(1)在子类成员函数中调用,但是要注意,在子类成员函数中调用是,要加上"父类名::成员函数名(…)的方式来调用"
例:子类构造中
Man::Man()
{
Human::sameFunc(); //可以调用
Human::sameFunc(123); //带参也可以调用
//两个函数都成功调用了父类的同名函数,Human::很关键
}
(2)如果Men是以public方式继承自Human父类,在main函数中,用"子类对象名.父类名::成员函数名(…)"的方式也能调用父类同名成员函数.
Men men;//实例一个子类
men.Human::sameFunc(123); //这里调用的是父类带参同名成员函数
men.Human::sameFunc(); //不带参,同样是父类
(3)可以通过using声明
public:
using Human::samenamefunc; //只能指定函数名,不能带形参列表,并且父类必须是public或\
protected(只能在子类成员函数中使用)
当然就算声明了using,在调用过程中,调用了跟子类同参同名函数,还是会优先调用子类,父类依旧会被覆盖.
想继续调用父类,还是要加Human::sameFunc() 父类名::同名函数(…)
总结
虽然子类可以调用父类的同名函数,但是实际意义可能并不大,如果子类覆盖了父类,那一般说明子类对象并不想调用父类,否则完全可以写成不同名的.