一:派生类概念
类之间有一种层次关系,有父类,有孩子类。比如车这个类,当成父类(也叫基类,超类),派生出卡车,轿车,他们属于孩子类(子类/派生类)
继承:有父亲类,有孩子类,构成了层次关系。继承这种概念,是面向对象程序设计的核心思想之一。
这种继承,就是我们要先定义一个父类。父类中定义一些公用的成员变量,成员函数。我们通过继承父类来构建新的类:子类。所以写代码时,只需写和子类相关的一些内容即可。子类一般会比父类更加庞大。
Human.h
#pragma once
#ifndef __HUMAN__
#define __HUMAN__
#include <iostream>
using namespace std;
class Human
{
public:
Human();
Human(int i);
public:
int m_Age;
char m_Name[100];
void funcPub() {};
void samenamefunc();
void samenamefunc(int i);
string samenamefunc(string s);
protected:
int m_pro1;
void funcPro() {};
private:
int m_priv1;
void funcPriv() {};
};
#endif // !__HUMAN__
Human.cpp
#include "Human.h"
Human::Human()
{
cout << "Human::Human()" << endl;
}
Human::Human(int age)
{
cout << "Human::Human(int age)" << endl;
}
void Human::samenamefunc()
{
cout << "Human::samenamefunc()" << endl;
}
void Human::samenamefunc(int i)
{
cout << "void Human::samenamefunc(int i)" << endl;
}
string Human::samenamefunc(string s)
{
cout << "string Human::samenamefunc(string s)" << endl;
return s;
}
Men.h
#pragma once
#ifndef __MEN__
#define __MEN__
#include "Human.h"
class Men:private Human
{
public:
Men();
using Human::samenamefunc;
public:
void samenamefunc();
};
#endif // !__MEN__
Men.cpp
#include "Men.h"
Men::Men()
{
cout << "Men::Men()" << endl;
}
void Men::samenamefunc()
{
cout << "Men::samenamefunc()" << endl;
//Human::samenamefunc();
//Human::samenamefunc(100);
}
Test.cpp
#include <iostream>
#include "Men.h"
using namespace std;
int main()
{
Men men;
men.samenamefunc();
men.samenamefunc(100);
cin.get();
return 0;
}
class Men :public Human。
class 子类名 : 继承方式,父类名
继承方式(访问等级/访问权限):public/protected/private;
二:派生类对象定义时调用构造函数的顺序
Men men;
父子类初始化谁先调用?当定义子类对象时,调用父类和子类的构造函数,且父类的构造函数体先执行,子类的构造函数体后执行。
三:public、protected、private
总结一下:三种访问权限
public:可以被任意实体所访问。
protected:只允许本类或者子类的成员函数来访问。
private:只允许本类的成员函数访问。
三种继承访问:
public 继承
protected 继承
private 继承
基类中的访问权限 | 子类继承基类的继承方式 | 子类得到的访问权限 |
public | public | public |
protected | public | protected |
public | public | public |
protected | public | protected |
private | public | 子类无权访问 |
public | protected | protected |
protected | protected | protected |
private | protected | 子类无权访问 |
public | private | private |
protected | private | private |
private | private | 子类无权访问 |
总结:
<1>子类public继承父类不改变父类的访问权限。
<2>protected继承将父类中public成员变为子类的protected成员。
<3>private继承使得父类所有成员在子类中的访问权限变为private。
<4>父类中的private成员不受继承方式的影响,子类永远无权访问。
<5>对于父类来讲,尤其是父类的成员函数,如果你不想让外边访问,就设置为private; 如果你想让自己的子类能够访问,就设置为protected,如果你想公开,就设置为public。
四、函数遮蔽
子类中如果有一个同名函数,那么父类中,不管有几个同名函数(不管是否带参数),子类中都无法访问到。
如果我们确实想调用父类中的同名函数怎么办?
<1>在子类的成员函数中,用父类 "父类::函数名"强制调用父类函数。
void Men::samenamefunc()
{
cout << "Men::samenamefunc()" << endl;
Human::samenamefunc();
Human::samenamefunc(100);
}
<2>using : using namespace
在 using c++11 中让父类同名函数在子类中可见。
通过 using 这个关键字,让父类的同名函数在子类中可见(让父类同名函数在子类中一重载的方式来使用)
说明:
<2.1>using Human::samenamefunc; 只能指定函数名,则凡是基类中public、protected的samenamefunc(基类中private不行)在子类中都可见。无法让一部分可见(函数重载全部可见)
<2.2>using 引入的主要目的是用来实现在子类中调用父类的重载版本。该函数在父类中的参数跟子类中的参数个数、类型不同。
Men men;
men.samenamefuc(12); 执行结果:执行了子类public::samenamefuc(int)的函数
men.samenamefuc();
class Men:private Human
{
public:
Men();
using Human::samenamefunc;
public:
void samenamefunc();
};
注:
若使用“using Human::samenamefunc;”语句:
<1>using的基类方法不能有private重载,就算子类已重写的方法也不行,否则会报错。 >“Human”: 并非所有的重载都可访问
<2>使用“using Human::samenamefunc;”语句后,调用父类,可以使public、protected、private均不报错。但必须要有调用父类。