C++ 中三种继承方式的理解
一、公有继承(public inheritance)
#include <iostream>
using namespace std; class A{
public:
A():x(),y(){}
A(int x){this->x = x;}
int getx(){return x;}
int gety(){return y;}
int getu(){return u;}
protected:
int y;
private:
int x;
int u;
};
//class B:public A{ //访问公有、保护成员
//
//};
class B:public A{ //通过A中的公有成员函数才能访问A中的私有成员,派生类的成员或者派生类的对象都无法直接访问基类私有成员
public:
// int getx(){return x;} //错误,直接用派生类的成员访问基类私有成员
// int getx(){return A::getx();}
int getx(){return ;} //改造基类成员函数
void sety(){y = ;} //直接调用基类保护成员并修改
};
int main(){
B b;
cout<<"原始的x:"<<b.A::getx()<<endl; //调用基类的同名函数
cout<<"改造后的x:"<<b.getx()<<endl; //调用改造后的函数
cout<<"保护成员y:"<<b.gety()<<endl;
b.sety();
cout<<"在派生类中修改y值:"<<b.gety()<<endl;
cout<<"私有成员u:"<<b.getu()<<endl; //公有继承可以通过派生类的对象访问基类继承的公有成员
// cout<<B::x<<endl; //错误,无法通过派生类成员访问基类私有成员
// cout<<b.y<<endl; //错误, 通过对象无法访问保护成员
return ;
}
执行结果:
理解:
公有继承方式:
在派生类内部:
1、 派生类成员可以直接访问基类的公有和保护类成员【上面代码23、25行】
2、 当然,如果想拓展继承来的函数可以进行改造,改造是可以同名的,
在接下来用对派生类的对象调用该函数时就会使用改造后的函数【上面代码24,29行】,
在后来的调用调用中仍然可以调用基类的未改造的函数【代码28行】
在派生类外部:
1、通过派生类的对象可以访问基类的公有成员(!这里只能访问公有成员,连保护成员都不可以访问)【上面代码35、36行】
2、无论是派生类的成员还是对象都无法直接访问基类私有成员【上面代码36、37行】
需要注意的是:如果派生类的成员函数与基类的成员函数且你想使用基类的那个函数功能,你需要用 '' 类名::'' 这种方式实现。(三种继承方式都是这样)
【上面代码23行】
二、私有继承(private inheritance)
#include <iostream>
using namespace std; class A {
public:
A() : x(), y() {}
int getx() { return x; }
int gety() { return y; }
int getu() { return u; }
protected:
int y;
private:
int x;
int u;
}; class B : private A {
public: //因为基类的公有、保护成员作为派生类的私有成员,派生类的成员不能直接访问它们,
int getx() { return A::getx(); } //只能通过成员函数调用它们 int getyy() { return gety(); } int getyyy(){return y;} //派生类成员中可以直接访问基类继承的公有和保护成员 }; int main() {
B b;
cout <<"x的值:" <<b.getx() << endl;
cout <<"y的值:"<< b.getyy() << endl;
cout<<"y的值:"<<b.getyyy()<<endl;
// cout<<b.getu()<<endl; //错误,私有继承无法通过派生类对象访问基类成员
return ;
}
执行结果:
理解:
私有继承方式:
在类的内部:
1、由于基类的公有成员和保护成员变成派生类的私有成员,派生类的成员可以直接访问它们【上面代码20、24行】
在类的外部:
1、派生类外部无法通过对象直接访问基类的公有成员和保护成员(这是与公有继承的一个差别)【上面代码33行】
在派生内外部: 都无法直接访问基类私有成员
三、保护继承(protected inheritance)
#include <iostream>
using namespace std; class A{
public:
A():x(),y(){}
int getx(){return x;}
int gety(){return y;}
int getu(){return u;}
protected:
int y;
private:
int x;
int u;
};
class B:protected A{
public:
int getxx(){return getx();} //派生类成员可以直接访问继承来的公有成员【与公有继承一样】
int getyy(){return y;}
};
int main(){
B b;
cout<<"x的值:"<<b.getxx()<<endl;
cout<<"y的值:"<<b.getyy()<<endl; // cout<<b.getx()<<endl; //通过派生类的对象无法直接访问基类成员【与私有继承一样】
// cout<<b.y<<endl;
}
执行结果:
理解:
保护继承方式:
在类内部:
1、继承的公有、保护成员以保护成员存在(存在方式与公有继承的以公有成员存在方式不同),派生类的其它成员可以直接访问
(这一点与公有、私有继承一致)。【上面代码18、19行】
在类外部:
1、通过派生类对象无法直接访问继承的公有、保护成员【上面代码26、27行】(与私有继承一样)
在派生类内外部:基类的私有成员都无法直接访问
#include <iostream>
using namespace std; class A{
public:
A():x(),y(){}
int getx(){return x;}
int gety(){return y;}
int getu(){return u;}
protected:
int y;
private:
int x;
int u;
};
class B:protected A{ //直接继承时 使用保护继承 再看二次继承的效果
public:
int getxx(){return getx();}
int getyy(){return y;}
};
//二次继承无论是私有还是保护继承,二次派生类都可以间接访问初始基类A的公有、保护成员
//class C:private B{
//public:
// int getA_x(){return getx();}
// int getA_y(){return y;}
//};
class D:protected B{
public:
int getA_x(){return getx();}
int getA_y(){return y;}
};
再看:直接继承时使用私有继承
代码如下:
#include <iostream>
using namespace std; class A{
public:
A():x(),y(){}
int getx(){return x;}
int gety(){return y;}
int getu(){return u;}
protected:
int y;
private:
int x;
int u;
};
class B2:private A{ //直接继承时 使用私有继承 再看二次继承的效果
public:
int getc_x(){return getx();}
int getc_y(){return gety();}
};
//二次继承无论时私有还是保护继承,都无法间接使用初始基类A的成员
class C2:private B2{
public:
// int getA_x(){return getx();} //错误,无法间接访问从初始基类A继承的成员
};
class D2:protected B2{
public:
// int getA_x(){return getx();} //错误,无法间接访问从初始基类A继承的成员
};
上面两块代码,我们主要看直接派生类 B&B2 的继承方式 and C&C2 、D&D2 能否调用初始基类A的成员
我们发现当直接派生类为私有继承时,通过它在派生的类无法间接访问最初基类成员,
而直接派生类为保护继承时,再通过它派生的成员则可以间接访问最初基类的公有、保护成员。
===============================================================================================================
以上为现阶段学习理解,如有错误,希望指正:)
最新文章
- Java 随机抽奖
- 关于Azure带宽的测试
- IOS 关键字self,super,copy, retain, assign , readonly , readwrite, nonatomic、 @synthesize、@property、@dynamic
- SourceTree 免登录跳过初始设置
- Linux 常用软件和服务的配置网站
- sybase ASE 12.5版本下载地址
- 自动开票-不能获取汇款地址 Cannot get remit to address
- [swustoj 771] 奶牛农场
- 【DFS+记忆搜索】NYOJ-10-Skiing
- Android模拟器——Genymotion
- [BZOJ 3489] A simple rmq problem 【可持久化树套树】
- LEK-Introduction
- 执行ANT JAVA三种方式
- windows环境下,anoconnda安装tensorflow
- Inno Setup打包注意事项
- ffmypeg 视频处理类库使用方法
- Altium Designer 10 执行DRC发现有 Length Constraint 解决办法
- 初识Quartz (一)
- 能够区分光驱的类型么?比如CDROM、DVD还是CD-RW
- uva11551矩阵快速幂