(继承)virtual与访问控制
之前只注意过访问控制与继承的关系,这边不多说,今天看到代码看到virtual放在private里,并且还有派生类没有override public里的virtual,此时调用时啥情况了,这边有点晕,看下面代码
首先最基本的多态代码
#include <iostream>
#include <string> using namespace std; class animal
{
public:
//animal();
//~animal();
virtual void speakout()
{
cout << "animal voice voice voice" << endl;
}
};
class cat :public animal
{
public:
//cat();
//~cat();
virtual void speakout()
{
cout << "cat miao miao miao" << endl;
}
}; int main()
{
cat ocat;
animal *panimal = &ocat;
panimal->speakout();
getchar(); }
运行结果没有任何问题,结果如下:

如果virtual是私有的,代码如下:
#include <iostream>
#include <string> using namespace std; class animal
{
private:
//animal();
//~animal();
virtual void speakout()
{
cout << "animal voice voice voice" << endl;
}
};
class cat :public animal
{
private:
//cat();
//~cat();
virtual void speakout()
{
cout << "cat miao miao miao" << endl;
}
}; int main()
{
cat ocat;
animal *panimal = &ocat;
panimal->speakout();
getchar(); }
编译就会报错,报错如下,实际上此时放在private里的时候,virtual有和没有一样,都是类的私有成员,只有类内部成员以及友元能够访问

主要是考虑下面一种特殊情况,基类里有virtual A(),派生类继承的时候没有override A(),切A()会调用私有的private virtual,代码如下:
#include <iostream>
#include <string> using namespace std; class animal
{
public:
virtual void speak()
{
speakout();
}
private:
//animal();
//~animal();
virtual void speakout()
{
cout << "animal voice voice voice" << endl;
}
};
class cat :public animal
{
private:
//cat();
//~cat();
virtual void speakout()
{
cout << "cat miao miao miao" << endl;
}
}; int main()
{
cat ocat;
animal *panimal = &ocat;
panimal->speak();
getchar(); }
其运行结果如下:

再对比如下代码:
#include <iostream>
#include <string> using namespace std; class animal
{
public:
virtual void speak()
{
speakout();
}
private:
//animal();
//~animal();
void speakout()
{
cout << "animal voice voice voice" << endl;
}
};
class cat :public animal
{
private:
//cat();
//~cat();
void speakout()
{
cout << "cat miao miao miao" << endl;
}
}; int main()
{
cat ocat;
animal *panimal = &ocat;
panimal->speak();
getchar(); }
其运行结果如下:

说明此时的private里的virtual是不能去掉的,如果去掉的话,speak()调用的是类本身的私有函数speakout(),否则调用的是派生类cat里的speakout()函数
当派生类继承了基类里的public speak(),哪怕没做任何修改,去掉private里的virtual,结果调用也是派生类里的speakout(),代码如下:
#include <iostream>
#include <string> using namespace std; class animal
{
public:
virtual void speak()
{
speakout();
}
private:
//animal();
//~animal();
void speakout()
{
cout << "animal voice voice voice" << endl;
}
};
class cat :public animal
{
public:
virtual void speak()
{
speakout();
}
private:
//cat();
//~cat();
void speakout()
{
cout << "cat miao miao miao" << endl;
}
}; int main()
{
cat ocat;
animal *panimal = &ocat;
panimal->speak();
getchar(); }
运行结果如下:

只能猜测派生类没有继承基类里的public speak(),panimal->speak()调用的是基类里的speak()函数,这时候间接调用的speakout()如果是虚函数则调用派生类的(哪怕是private),否则调用基类的
当继承了基类里的public speak(),panimal->speak()直接就调用了派生类里的speakout(),这时候speakout()是不是虚函数已没有关系
这边的原理我也没搞懂,只知道现在用起来是这样,如果哪位大神知道原理的能和我讲下,不甚感激!!!!!!!!!!!
(继承)virtual与访问控制的更多相关文章
- C++(三十八) — 继承方式、访问控制、构造和析构、虚继承
派生类继承了基类的所有成员,但不包含 构造函数.析构函数.默认赋值运算符. 1.继承方式.访问控制 (1)protected属性:类的对象不能访问该属性成员,但派生类的成员函数可以访问基类的prot ...
- C++对象内存分布(3) - 菱形继承(virtual)
1.前言 本篇文章的全部代码样例.假设是windows上编译执行.则使用的是visual studio 2013.假设是RHEL6.5平台(linux kernal: 2.6.32-431.el6.i ...
- inheritance,菱形继承, 虚继承,virtual
//菱形继承 ||||||| 虚继承 #include <iostream> using namespace std; class R { int r; public: ...
- C++学习之继承中的访问控制
我们通常认为一个类有两种不同的用户:普通用户 和 类的实现者.其中,普通用户编写的代码使用类的对象,这部分代码只能访问类的公有(接口)成员:实现者则负责编写类的成员和友元的代码,成员和友元既能访问类的 ...
- C++ 类的继承一(访问控制)
//类的继承 #include<iostream> using namespace std; /* 面向对象中的继承类之间的父子关系 1.子类拥有父类所有的成员属性和成员函数(包括私有成员 ...
- C++复习:继承与派生
1继承概念 面向对象程序设计有4个主要特点:抽象.封装.继承和多态性.说了类和对象,了解了面向对象程序设计的两个重要特征一数据抽象与封装,已经能够设计出基于对象的程序,这是面向对象程序设计的基础. 要 ...
- C++基础 (6) 第六天 继承 虚函数 虚继承 多态 虚函数
继承是一种耦合度很强的关系 和父类代码很多都重复的 2 继承的概念 3 继承的概念和推演 语法: class 派生类:访问修饰符 基类 代码: … … 4 继承方式与访问控制权限 相对的说法: 爹派生 ...
- C++ 的多继承与虚继承
C++之多继承与虚继承 1. 多继承 1.1 多继承概念 一个类有多个直接基类的继承关系称为多继承 多继承声明语法 class 派生类名 : 访问控制 基类名1, 访问控制 基类名2, ... { ...
- Effective C++ -- 继承和面向对象设计
32.确保你的public继承了模is-a关系 public继承意味着is-a关系(里氏替换原则),一切适用于基类也适用于派生类. 矩形继承正方形问题: 可实施与矩形的操作无法实施与正方形 在编程领域 ...
随机推荐
- [SinGuLaRiTy] 树形DP专项测试
[SinGuLaRiTy-1015] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 对于所有的题目:Time Limit:1s | Me ...
- UIDatePicker的使用
UIDatePicker的介绍 UIDatePicker这个类的对象让用户可以在多个车轮上选择日期和时间.iPhone手机上的‘时钟’应用程序中的时间与闹铃中便使用了该控件.使用这个控件时,如果你能配 ...
- Android 学习笔记之 个人认为最简单的查看Android源码方案
相信很多人都会疑惑如何使用Eclipse ADT查看源码? 下面我们将介绍 如何查看Android源码. 本文有如下优点: 1.不用费心去找Android源码地址:一个字烦,网上的东西杂七杂八的... ...
- JS中遍历语法的比较
for循环 JavaScript 提供多种遍历语法.最原始的写法就是for循环.(假设myArray是数组,下面同理) let arr = [1,2,3,4,5]; for (var index = ...
- android 开机自启动实现
App的开机自启动可以通过注册广播接收器接收开机广播来实现,具体步骤如下: 1.创建 BroadcastReceiver 的派生类,并重写 onReceive() 函数: /** * Created ...
- 封装Echarts
项目中需要对数据进行图形展示,例如展示柱状图.饼状图等.这类的前端展示脚本很多,常见的是HighCharts和Echarts.HighCharts是基于svg技术的,而echarts基于Echarts ...
- quartus ii中仿真rom时遇到的问题(待完善)
1.modelsim仿真只支持.hex,并不支持.mif(Memory Initialzation File). 2.在Matlab中生成.mif文件,然后再quartus中打开,转换为hex格式后另 ...
- python 实例方法,类方法和静态方法
在学习python代码时,看到有的类的方法中第一参数是cls,有的是self,经过了解得知,python并没有对类中方法的第一个参数名字做限制,可以是self,也可以是cls,不过根据人们的惯用用法, ...
- 读书笔记 effective c++ Item 47 使用traits class表示类型信息
STL主要由为容器,迭代器和算法创建的模板组成,但是也有一些功能模板.其中之一叫做advance.Advance将一个指定的迭代器移动指定的距离: template<typename IterT ...
- 设计模式总结(Java)—— 适配器模式
适配器模式中引入了一个被称为适配器(Adapter)的包装类,而它所包装的对象称为适配者(Adaptee),即被适配的类.适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用.也就是说:当客户 ...