一、基类

    从一个类派生出另一个类时,原始类称为基类,继承类称为派生类。

派生类对自身基类的private成员没有访问权限,对基类对象的protected成员没有访问权限,对派生类对象的(基类之外)的private和protected成员具有访问权限。

由于C++基础不好,平时也不用它,导致今天才纠正一个非常关键的错误,类的访问权限,是对类而言的,而不是对类的对象而言的。一直都理解错了。这句话都没脸写出来,还是写下来了。

下面是一段简答的测试代码。对于调用成员函数的对象test,基类形参,派生类形参三者的访问权限做了测试如下:

    #include <iostream>
using namespace std; class base
{
public:
int pub;
protected:
int pro;
private:
int pri;
}; class derive : public base
{
public:
int newpub;
protected:
int newpro;
private:
int newpri; public:
int func(class base a, class derive b)
{
//////////////////////////////////////////
自身的 基类成员和非基类成员访问权限测试
cout << newpub << endl;
cout << newpro << endl;
cout << newpri << endl;
cout << pub << endl;
cout << pro << endl;
// no access cout << pri << endl; /////////////////////////////////////////
对基类对象访问权限的测试
cout << a.pub << endl;
// no access cout << a.pro << endl;
// no access cout << a.pri << endl; /////////////////////////////////////////
对派生类对象的基类以及非基类成员访问权限测试
cout << b.pub << endl;
cout << b.pro << endl;
//no access cout << b.pri << endl;
cout << b.newpub << endl;
cout << b.newpro << endl;
cout << b.newpri << endl;
//////////////////////////////////////// return 0;
}
}; int main()
{
class base a;
class derive b;
class derive test;
test.func(a, b);
return 0;
}

 

对基类进行继承时,三种继承方式下,基类的三种访问权限在子类中会有如何的变化这个问题,本科时上C++这门课的时候曾仔细的分析并弄得挺清楚,后来时间久了、用的也不多,慢慢的又变得心里不太有谱了。这次接着准备面试的契机,又重新仔细分析了一番,留个案底,以免再犯糊涂。

三种访问权限

public:可以被任意实体访问
    protected:只允许子类及本类的成员函数访问
    private:只允许本类的成员函数访问

三种继承方式

public 继承  
    protect 继承
    private 继承

组合结果

基类中      继承方式             子类中

public     & public继承        => public
    public     & protected继承     => protected  
    public     & private继承      
=> private

protected  & public继承        => protected
    protected  & protected继承     => protected  
    protected  & private继承       => private

private    & public继承        => 子类无权访问
    private    & protected继承     => 子类无权访问
    private    & private继承       => 子类无权访问

由以上组合结果可以看出

1、public继承不改变基类成员的访问权限
    2、private继承使得基类所有成员在子类中的访问权限变为private
    3、protected继承将基类中public成员变为子类的protected成员,其它成员的访问       权限不变。
    4、基类中的private成员不受继承方式的影响,子类永远无权访问。

此外,在使用private继承时,还存在另外一种机制:准许访问。

我们已经知道,在基类以private方式被继承时,其public和protected成员在子类中变为private成员。然而某些情况下,需要在子类中将一个或多个继承的成员恢复其在基类中的访问权限。

C++支持以两种方式实现该目的

方法一,使用using 语句,这是C++标准建议使用的方式
    方法二,使用访问声明,形式为 base-class::member;,位置在子类中适当的访问声明处。(注,只能恢复原有访问权限,而不能提高或降低访问权限)

以下是简单的试验代码 

#include <iostream>

using namespace std;

class Grand
{
public:
void public_foo (){}
protected:
void protected_foo(){}
private:
void private_foo(){}
}; class Father:public Grand
{
public:
void f_public_test() {public_foo(); }
void f_protected_test() {protected_foo(); }
// void f_private_test() {private_foo(); }
}; class Child:public Father
{
public:
void c_protected_test() {protected_foo(); }
// void c_private_test() {private_foo();}
}; int main( int argc, char* argv[])
{
Father objF; // objF.protected_foo(); return 1; } //protected.cpp #include <iostream> using namespace std; class Grand
{
public:
void public_foo (){}
protected:
void protected_foo(){}
private:
void private_foo(){}
}; class Father:protected Grand
{
public:
void f_public_test() {public_foo(); }
void f_protected_test() {protected_foo(); }
// void f_private_test() {private_foo(); }
}; class Child:public Father
{
public:
void c_protected_test() {protected_foo(); }
// void c_private_test() {private_foo();}
}; int main( int argc, char* argv[])
{
Father objF; // objF.public_foo();
// objF.protected_foo(); return 1; } //private.cpp #include <iostream> using namespace std; class Grand
{
public:
void public_foo (){}
protected:
void protected_foo(){}
private:
void private_foo(){}
}; class Father:private Grand
{
public:
void f_public_test() {public_foo(); }
void f_protected_test() {protected_foo(); }
// void f_private_test() {private_foo(); }
}; class Child:public Father
{
public:
// void c_protected_test() {protected_foo(); }
// void c_private_test() {private_foo();}
}; int main( int argc, char* argv[])
{
Father objF; // objF.public_foo();
// objF.protected_foo(); return 1; }

C++ primer(十三)--类继承、构造函数成员初始化、虚函数、抽象基类的更多相关文章

  1. OOP2(虚函数/抽象基类/访问控制与继承)

    通常情况下,如果我们不适用某个函数,则无需为该函数提供定义.但我们必须为每个虚函数都提供定义而不管它是否被用到了,这因为连编译器也无法确定到底会适用哪个虚函数 对虚函数的调用可能在运行时才被解析: 当 ...

  2. 构造函数为什么不能为虚函数 &amp; 基类的析构函数为什么要为虚函数

    一.构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数相应一个指向vtable虚函数表的指针,这大家都知道,但是这个指向vtable的指针事实上是存储在对象的内存空间的.问题出来了,假设构造函数 ...

  3. C++ 虚函数在基类与派生类对象间的表现及其分析

    近来看了侯捷的<深入浅出MFC>,读到C++重要性质中的虚函数与多态那部分内容时,顿时有了疑惑.因为书中说了这么一句:使用“基类之指针”指向“派生类之对象”,由该指针只能调用基类所定义的函 ...

  4. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

  5. c++之——抽象基类

    在一个虚函数的声明语句的分号前加上 =0:就可以将一个虚函数变成纯虚函数,其中,=0只能出现在类内部的虚函数声明语句处.纯虚函数只用声明,而不用定义,其存在就是为了提供接口,含有纯虚函数的类是抽象基类 ...

  6. C++基类的析构函数定义为虚函数的原因

    1:每个析构函数只会清理自己的成员(成员函数前没有virtual).2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类 ...

  7. python(七):元类与抽象基类

    一.实例创建 在创建实例时,调用__new__方法和__init__方法,这两个方法在没有定义时,是自动调用了object来实现的.python3默认创建的类是继承了object. class A(o ...

  8. thrift之TTransport类体系原理及源码详细解析1-类结构和抽象基类

    本章主要介绍Thrift的传输层功能的实现,传输的方式多种多样,可以采用压缩.分帧等,而这些功能的实现都是相互独立,和上一章介绍的协议类实现方式比较雷同,还是先看看这部分的类关系图,如下: 由上面的类 ...

  9. Python 接口:从协议到抽象基类

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Helvetica } 抽象基类的常见用途:实现接口时作为超类使用.然后,说明抽象基类如何检查 ...

  10. 【Python】【元编程】【从协议到抽象基类】

    """class Vector2d: typecode = 'd' def __init__(self,x,y): self.__x = float(x) self.__ ...

随机推荐

  1. JavaScrip——简单练习(抓错误信息,for循环,日期)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. java——多线程的实现

    package test; class TestThread extends Thread{ public void run() { for(int n=0;n<3;n++) { try{Thr ...

  3. win10无法访问局域网共享文件?(因微软账户和本地账户登陆问题导致)

    1 笔记本系统win10 X64企业版,其中一文件夹已设置为“共享”.本地帐号登录系统. 2 平板电脑系统win8.1 X64专业版,可以顺畅的访问笔记本的共享文件.微软帐号登录系统. 3 平板电脑系 ...

  4. zip文件内存中解压读取

    // 构造zip输入流 ZipInputStream zip = new ZipInputStream(fis,Charset.forName("gbk")); byte[] tm ...

  5. 彻底解决java WEB项目的文件路径问题(war包)

    在j2EE项目中,我们通常会把项目打包公布,通常是war包,作为独立单元,能够远程上传,载入,公布,还能够实现版本号控制,但这与我们开发过程中使用MyEclipse自己主动部署有所不同,下面做具体说明 ...

  6. SQL Server 查询分析器键盘快捷方式

    下表列出 SQL Server 查询分析器提供的所有键盘快捷方式. 活动 快捷方式 书签:清除所有书签. CTRL-SHIFT-F2 书签:插入或删除书签(切换). CTRL+F2 书签:移动到下一个 ...

  7. python将数据写入mysql乱码的解决办法

    1.错误为:插入乱码 报错: Python模块MySQLdb操作mysql出现2019错误:Can't initialize character set utf-8 解决: 写入数据语句为: cnn ...

  8. 5个界面效果很炫的JavaScript UI 框架

    Web 开发很简单,Web 应用的 UI 开发却很复杂,如果能够利用一些成熟的 UI 框架可以大大的减少开发的复杂度.本文向你介绍 5 款界面效果很不错的 JS 框架. 1. ExtJS ExtJS ...

  9. 【MySQL】字符串截取之substring_index

    substring_index(str,delim,count)       str:要处理的字符串       delim:分隔符       count:计数 例子:str=www.baidu.c ...

  10. i2c驱动笔记

    基于bcm5300x芯片 注册平台总线设备,设备名bcm5300x_i2c,通过名称与驱动进行匹配. 注册平台总线驱动.驱动名称"bcm5300x_i2c",与设备进行匹配. dr ...