当前课程知识点:C++语言程序设计进阶 >  第七章 继承与派生 >  继承方式 >  私有继承和保护继承

返回《C++语言程序设计进阶》慕课在线视频课程列表

私有继承和保护继承在线视频

私有继承和保护继承

注意:视频中“多继承举例”程序代码有误,请看下面更正的代码(多继承举例(补7-2))

私有继承和保护继承

私有继承(private) 

例7-2 私有继承举例

Point.h

#ifndef _POINT_H
#define _POINT_H
class Point {   //基类Point类的定义
public: //公有函数成员
    void initPoint(float x = 0, float y = 0) 
  { this->x = x; this->y = y;}
    void move(float offX, float offY) 
  { x += offX; y += offY; }
    float getX() const { return x; }
    float getY() const { return y; }
private:    //私有数据成员
    float x, y;
};  
#endif //_POINT_H

Rectangle.h

#ifndef _RECTANGLE_H
#define _RECTANGLE_H
#include "Point.h"
class Rectangle: private Point {    //派生类定义部分
public: //新增公有函数成员
    void initRectangle(float x, float y, float w, float h) {
        initPoint(x, y); //调用基类公有成员函数
        this->w = w;
        this->h = h;
    }
    void move(float offX, float offY) {   Point::move(offX, offY);  }
    float getX() const { return Point::getX(); }
    float getY() const { return Point::getY(); }
    float getH() const { return h; }
    float getW() const { return w; }
private:    //新增私有数据成员
    float w, h;
};
#endif //_RECTANGLE_H

main.cpp

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    Rectangle rect; //定义Rectangle类的对象
    rect.initRectangle(2, 3, 20, 10);   //设置矩形的数据
    rect.move(3,2); //移动矩形位置
    cout << "The data of rect(x,y,w,h): " << endl;
    cout << rect.getX() <<", "  //输出矩形的特征参数
        << rect.getY() << ", "
        << rect.getW() << ", "
        << rect.getH() << endl;
    return 0;
}

保护继承(protected)

protected 成员举例(补7-1)

class A {
protected:
    int x;
};

int main() {
    A a;
    a.x = 5;//错误
}
class A {
protected:
    int x;
};
class B: public A{
public:
    void function();
};
void B:function() {
    x = 5;   //正确
}

多继承举例(补7-2)

class A {
public:
    void setA(int);
    void showA() const;
private:
    int a;
};
class B {
public:
    void setB(int);
    void showB() const;
private:
    int b;
};
class C : public A, private B { 
public:
    void setC(int, int, int);
    void showC() const;
private:
    int c;
};

多继承举例

void  A::setA(int x) {
    a=x; 
}
void B::setB(int x) {
    b=x; 
}
void C::setC(int x, int y, int z) {
    //派生类成员直接访问基类的
    //公有成员
    setA(x); 
    setB(y); 
    c = z;
}

//其他函数实现略

int main() {
    C obj;
    obj.setA(5);
    obj.showA();
    obj.setC(6,7,9);
    obj.showC();
// obj.setB(6);  错误
// obj.showB(); 错误
    return 0;
}



下一节:基类与派生类类型转换

返回《C++语言程序设计进阶》慕课在线视频列表

私有继承和保护继承课程教案、知识点、字幕

大家好

欢迎回来继续学习

C++语言程序设计

私有继承呢

是最严格的一种继承

基类的公有和保护成员

继承过来以后呢

都变成了私有成员了

那么基类中的原来私有成员

当然还是不可以直接访问

那这种继承呢

其实用得不多

用的时候呢

你要明确目标

为什么要私有继承

实际上它起到了一个

将基类的原有对外接口

都给它封闭掉的这样一个作用

那么基类继承过来的成员

在派生类之外

通过派生类的对象

就不能直接访问了

那么基类继承过来的公有

和保护成员呢

在派生类的内部

还可以访问

接下来呢

我给大家演示一个

私有继承的例子

在这个例子中呢

我们还是定义一个点类

然后让矩形类继承点类

只不过呢这一次

我们让矩形类

以私有方式来继承点类

然后还是在主函数中

定义矩形类的对象

通过矩形类的对象呢

去调用它的成员函数

这一次看看

调用的是哪个类定义的成员函数

好 我们通过单步执行跟踪进去

看看现在调用的移动

是哪个函数

我们跟踪进去

我们看是进到了

Rectangle的成员函数中

在这个例题中

我们看到

在Rectangle类里面

自己也定义了一个move函数

为什么呢

因为point类的move函数

被继承到Rectangle类以后

就成了私有的了

因为它是私有继承

私有成员函数呢

在类外通过对象

是不能直接调用的

那么我们去

怎么去移动一个矩形呢

虽然私有的成员函数

在类外不能被调用

但是在类体里面

在类的成员函数里面

我们是可以使用它的

所以呢

在这儿我们通过

基类类名和作用域分辨符

在这里调用从基类继承过来的

这个move函数

也就是点类的move函数

这样就达到了

移动矩形的这样一个目的

同样呢

getX getY函数也是一样的

我们继续运行

接下来我们需要进到

这些get函数里面了

第一次还是进到

自己定义的Rectangle定义的

getH函数里面了

执行完了以后

再执行进入到

Rectangle自己定义的getW

函数里面了

接下来呢

进到了getY函数里面

这一次是Rectangle自己定义的

因为基类继承过来了getY

在类外也不能直接被访问了

但是在本类的成员函数中

它是可以访问的

所以呢

在Rectangle的getY函数中

调用了point类继承过来的

这个getY函数

取得了Y坐标的值 返回

同样

getX函数也是一样

调用了Rectangle类

自己定义的getX函数

那么通过这个例子我们就看到了

以私有方式继承的时候

公有成员

到了派生类中也成了私有的

在类外不能直接访问了

这样派生类呢就要解决

必要的这种访问接口的问题

所以Rectangle类

自己定义了一些新的访问接口

那么在函数体中

调用了基类继承过来的函数

保护继承呢

是介于公有和私有之间的一种

继承方式

从第四章开始

大家就一直存着一个疑问

保护成员到底是什么

那么保护继承的时候

基类的公有成员和保护成员

到了派生类以后

都成保护成员了

这个保护成员它的特点就是

派生类中的成员函数

是可以直接访问它的

那么基类的保护成员

到了派生类以后

还是保护成员

大家看到了

不管公有继承还是保护继承

都是基类的保护成员

到了派生类中

还是保护成员

那么也就是说

这个保护成员

它向下派生的时候

是可以被派生类成员

直接访问的

但是在类外呢

在整个类家族之外呢

它就像私有成员一样

是不能被访问的

这就是保护成员的特点

所以经过保护继承以后

在类外通过派生类的对象

就不能访问那些

从基类继承过来的成员了

只能派生类新增的成员

保护成员的特点呢

我们简单归纳一下

对于建立其所在类

对象的模块来说

它与私有成员的性质相同

对于它的派生类来说

它与公有成员的性质相同

既实现了数据隐藏

又方便继承

实现了代码的重用

下面的例题呢

对比了从不同的位置

访问保护成员时候的情况

我们看这里定义了一个类a

其中有一个保护成员x

那这个x在类外能不能访问呢

我们测试一下

定义一个主函数

在主函数中

定义一个A类的对象a

我们试图用a.x的方式

去访问对象A的保护成员

这个时候编译器会给我们报错

因为保护成员在类外去看它

就像私有的一样

它是不可直接访问的

但是呢

如果我们定义一个B

作为派生类去继承A类

用公有的方式继承A类

那么A的类的保护成员

就被继承到B类里面来了

这个时候

我们在B类的成员函数中

直接访问这个保护成员x

这就是可以的

就是正确的

所以保护成员呢

当它以公有方式和保护方式

继承到派生类中以后

派生类的成员函数

是可以访问它的

但是在类外是不可访问

这就是保护成员它的特点

大家看到了

这样的保护成员语法以后

是不是感觉保护成员挺好

它既然能够对于类家族之外

隐藏细节

又能够让这个成员

能被派生类访问

两全其美

是不是很好呢

其实保护成员呢有它的优势

但是也要慎用

用在什么场合可以呢

如果基类和派生类

都是我们自己写的

我们这一个项目

一个团队自己写的

这没有问题

如果说

基类和派生类

不是同一组人写的

或者你干脆是通过某种途径

去买的类库等等

那么那个时候

你去用它的保护成员的细节

就不那么方便了

这个深入的东西

大家可以自己想一想

是不是这么回事

如果派生类有多个基类

也就是多继承的时候

那么每个基类

我们可以采用不同的继承方式

先来看看这个例题

在这里我们定义了A类和B类

定义了C类呢

继承了A和B

它继承两个类

它是以公有方式继承A

以私有方式继承B

A类和B类各自有自己的数据成员

和相应的公有访问接口

它的公有成员函数

C类也自己新增了数据成员

除了继承以外

然后也定义了自己的成员函数

那么我们来看

C类的成员函数

setC它的实现

这些函数是为了给数据成员

设置值

但是它直接设置

直接赋值

只能给自己类新增的

这个成员c赋值

那么从A类继承来的成员

从B类继承来的成员

都要调用C类的公有成员函数

来进行设置

在主函数中

我们定义了C类的对象 obj

那么这个对象

通过这个对象调用setA

showA没有问题

A类的公有成员

被继承到C类中来

仍然是公有成员

调用C类自己新增的公有成员

setC showC也没有问题

但是如果你试图调用

B类的成员函数

那编译器就会给我们报错

为什么呢

因为B类是私有继承的

B类的函数

公有函数到了C里面

也变成私有的了

在类外就不能直接访问了

C++语言程序设计进阶课程列表:

第七章 继承与派生

-导学

--导学

-继承的基本概念和语法

--继承的基本概念和语法

-第七章 继承与派生--继承的基本概念和语法习题

-继承方式

--继承方式简介及公有继承

--私有继承和保护继承

-第七章 继承与派生--继承方式

-基类与派生类类型转换

--基类与派生类类型转换

-第七章 继承与派生--基类与派生类类型转换

-派生类的构造和析构

--派生类的构造函数

--派生类的构造函数举例

--派生类的复制构造函数

--派生类的析构函数

--第七章 继承与派生--派生类的构造和析构

-派生类成员的标识与访问

--访问从基类继承的成员

--虚基类

-第七章 继承与派生--派生类成员的标识与访问

-小结

--小结

-综合实例

--第七章综合实例

-实验七

--实验七

-第七章讲义

第八章 多态性

-导学

--导学

-第八章 多态性--导学

-运算符重载

--运算符重载的规则

--双目运算符重载为成员函数

--单目运算符重载为成员函数

--运算符重载为非成员函数

-第八章 多态性--运算符重载

-虚函数

--虚函数

--虚析构函数

--虚表与动态绑定

-第八章 多态性--虚函数

-抽象类

--抽象类

--第八章 多态性--抽象类

-override与final

--override与final

-第八章 多态性--override与final

-小结

--第八章小结

-综合实例

--第八章综合实例

-实验八

--实验八

- 第八章讲义

第九章 模板与群体数据

-导学

--导学

-模板

--函数模板

--类模板

-第九章 模板与群体数据--模板

-线性群体

--线性群体的概念

-第九章 模板与群体数据--线性群体

-数组

--数组类模板

--例9-4数组类应用举例

-链表

--链表的概念与结点类模板

--链表类模板

-第九章 模板与群体数据--链表

-栈

--栈类模板

--栈类模板课后习题

--例9-9 栈的应用

--例9-9 栈的应用课后习题

-队列

--队列类模板

-第九章 模板与群体数据--队列

-排序

--排序概述

--插入排序

--选择排序

--交换排序

-第九章 模板与群体数据--排序

-查找

--查找

--查找课后习题

-小结

--小结

-综合实例

--综合实例

-实验九

--实验九

- 第九章讲义

第十章 泛型程序设计与C++标准模板库

-导学

--导学

-泛型程序设计及STL的结构

--泛型程序设计的基本概念

--STL简介

-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构

-迭代器

--迭代器

-第十章 泛型程序设计与C++标准模板库--迭代器

-容器的基本功能与分类

--容器的基本功能与分类

-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类

-顺序容器

--顺序容器的基本功能

--顺序容器的特征

--顺序容器的插入迭代器与适配器

--第十章 泛型程序设计与C++标准模板库--顺序容器

-关联容器

--关联容器分类和基本功能

--集合

--映射

--多重集合和多重映射

-第十章 泛型程序设计与C++标准模板库--关联容器

-函数对象

--函数对象

--函数适配器

-算法

--算法

-小结

--第十章小结

-综合实例

--综合实例

-实验十

--实验十

- 第十章讲义

第十一章 流类库与输入/输出

-导学

--导学

-I/O流的概念及流类库结构

--I/O流的概念及流类库结构

-第十一章 流类库与输入/输出--I/O流的概念及流类库结构

-输出流

--输出流概述

--向文本文件输出

--向二进制文件输出

--向字符串输出

-第十一章 流类库与输入/输出--输出流

-输入流

--输入流概述

--输入流应用举例

--从字符串输入

-第十一章 流类库与输入/输出--输入流

-输入/输出流

--输入/输出流

-第十一章 流类库与输入/输出--输入/输出流

-小结

--小结

-综合实例

--综合实例

-实验十一

--实验十一

- 第十一章讲义

第十二章 异常处理

-导学

--第12章导学

-异常处理的思想与程序实现

--异常处理的思想与程序实现

-第十二章 异常处理--异常处理的思想与程序实现

-异常处理中的构造与析构

--异常处理中的构造与析构

-第十二章 异常处理--异常处理中的构造与析构

-标准程序库异常处理

--标准程序库异常处理

-第十二章 异常处理--标准程序库异常处理

-小结

--第12章小结

-综合实例

--综合实例

-实验十二

--实验十二

- 第十二章讲义

私有继承和保护继承笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。