一、基类

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

派生类对自身基类的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. 【WPF】ListBox无法滚动

    问题:ListBox显示多个条目时,无法滚动,也不显示滚动条. 办法: 给ListBox控件加上ScrollViewer.VerticalScrollBarVisibility和ScrollViewe ...

  2. C语言 · 分糖果

    历届试题 分糖果   时间限制:1.0s   内存限制:256.0MB      问题描述 有n个小朋友围坐成一圈.老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏: 每个小朋友都把自己的糖果分一 ...

  3. 数据库——SQL中EXISTS怎么用2(转)

    数据库sql语句的exists总结 sql exists in 学习 先来比较下语法: --deals=交易表,areas=地域表,例如香港:我们的目的:查看有交易的地域 select * from ...

  4. Hbase 学习(一) hbase配置文件同步

    最近在狂啃hadoop的书籍,这部<hbase:权威指南>就进入我的视野里面了,啃吧,因为是英文的书籍,有些个人理解不对的地方,欢迎各位拍砖. HDFS和Hbase配置同步 hbase的配 ...

  5. Java-jdbc连接简化类jdbcUtil

    在src文件夹下创建配置文件 db.properties db.properties drivername=com.mysql.jdbc.Driver url=jdbc:mysql://localho ...

  6. JSDoc 3 生成javascript API文档

    一.javascript注释规范 我们在编写javascript文件的时候,一般会添加一些注释.例如一些文件.类.方法和属性都应该用合适的标记和类型进行注释.这里不但方便我们的阅读,也能养成一个好的习 ...

  7. 登录centos虚拟机后显示-bash-4.1

    http://zhidao.baidu.com/link?url=KwpGOdwFw1oxnL71pvPlfRgbRL_IuQeYRzIYJjiDb2SnX0dQye5yUXqHAGSyuD6u2nD ...

  8. Spring IO platform 简介

    前提:熟悉Spring基础知识. 简介:Spring IO Platform将 the core Spring APIs 集成到一个Platform中.它提供了Spring portfolio中的大量 ...

  9. VS2008兼容安装

    1. 直接安装出现问题:该项目的所有配置都需要系统提供对某些 平台的支持,但在此计算机上没有安装这些平台.因此无法加载该项目. 解决方法:先卸载原来安装的, 再设置安装包中的setup.exe的兼容性 ...

  10. 不可将布尔变量直接与 TRUE、FALSE 或者 1、0 进行比较

    不可将布尔变量直接与 TRUE.FALSE 或者 1.0 进行比较. 根据布尔类型的语义,零值为“假”(记为 FALSE),任何非零值都是“真”(记为 TRUE). TRUE 的值究竟是什么并没有统一 ...