之前只注意过访问控制与继承的关系,这边不多说,今天看到代码看到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与访问控制的更多相关文章

  1. C++(三十八) — 继承方式、访问控制、构造和析构、虚继承

    派生类继承了基类的所有成员,但不包含 构造函数.析构函数.默认赋值运算符.  1.继承方式.访问控制 (1)protected属性:类的对象不能访问该属性成员,但派生类的成员函数可以访问基类的prot ...

  2. C++对象内存分布(3) - 菱形继承(virtual)

    1.前言 本篇文章的全部代码样例.假设是windows上编译执行.则使用的是visual studio 2013.假设是RHEL6.5平台(linux kernal: 2.6.32-431.el6.i ...

  3. inheritance,菱形继承, 虚继承,virtual

    //菱形继承   |||||||   虚继承 #include <iostream> using namespace std; class R {     int r; public:   ...

  4. C++学习之继承中的访问控制

    我们通常认为一个类有两种不同的用户:普通用户 和 类的实现者.其中,普通用户编写的代码使用类的对象,这部分代码只能访问类的公有(接口)成员:实现者则负责编写类的成员和友元的代码,成员和友元既能访问类的 ...

  5. C++ 类的继承一(访问控制)

    //类的继承 #include<iostream> using namespace std; /* 面向对象中的继承类之间的父子关系 1.子类拥有父类所有的成员属性和成员函数(包括私有成员 ...

  6. C++复习:继承与派生

    1继承概念 面向对象程序设计有4个主要特点:抽象.封装.继承和多态性.说了类和对象,了解了面向对象程序设计的两个重要特征一数据抽象与封装,已经能够设计出基于对象的程序,这是面向对象程序设计的基础. 要 ...

  7. C++基础 (6) 第六天 继承 虚函数 虚继承 多态 虚函数

    继承是一种耦合度很强的关系 和父类代码很多都重复的 2 继承的概念 3 继承的概念和推演 语法: class 派生类:访问修饰符 基类 代码: … … 4 继承方式与访问控制权限 相对的说法: 爹派生 ...

  8. C++ 的多继承与虚继承

    C++之多继承与虚继承   1. 多继承 1.1 多继承概念 一个类有多个直接基类的继承关系称为多继承 多继承声明语法 class 派生类名 : 访问控制 基类名1, 访问控制 基类名2, ... { ...

  9. Effective C++ -- 继承和面向对象设计

    32.确保你的public继承了模is-a关系 public继承意味着is-a关系(里氏替换原则),一切适用于基类也适用于派生类. 矩形继承正方形问题: 可实施与矩形的操作无法实施与正方形 在编程领域 ...

随机推荐

  1. Androidstudio2.0.0下载,欢迎下载

    Androidstudio开发工具很实用,但是没了Google下载还是蛮麻烦的,所以呢Eric就向大家提供了下载的地址,其实就是从自己网盘考过来的,大家可以下载的. http://pan.baidu. ...

  2. String 类的实现(1)浅拷贝存在的问题

    浅拷贝 : 也称位拷贝 , 编译器只是直接将指针的值拷贝过来, 结果多个对象共用 同 一块内 存, 当一个对象将这块内 存释放掉之后, 另 一些对象不知道该块空间 已经还给了 系 统, 以 为还有效, ...

  3. 【原创】Octovis在Ubuntu16.04下运行出现core dump的解决方案

    本人SLAM研究新手,使用系统为Ubuntu16.04.本文原址:http://www.cnblogs.com/hitlrk/p/6667253.html 在学习SLAM的过程中,使用Octomap进 ...

  4. Wireless Intranet Captive Portal

    Wireless Intranet Captive Portal 配置AAA服务Radius认证 radius-server key 0 radius radius-server authentica ...

  5. GPU加速有坑?

    大多数人都知道有动画的地方可以使用GPU来加速页面渲染. 例如,做优化的时候,将使用left和top属性的动画修改成使用transform属性的CSS动画.或者听到别人教你使用transform:tr ...

  6. 读书笔记 effective c++ Item 46 如果想进行类型转换,在模板内部定义非成员函数

    1. 问题的引入——将operator*模板化 Item 24中解释了为什么对于所有参数的隐式类型转换,只有非成员函数是合格的,并且使用了一个为Rational 类创建的operator*函数作为实例 ...

  7. Java -- 浅入Java反射机制

    1,Java 反射是Java语言的一个很重要的特征,它使得Java具体了"动态性". Java 反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类. 在运行时构造任意一 ...

  8. js的break语句,continue语句,return语句

    js的break语句,continue语句,return语句. 用的时候很容易混淆,有过一次泪奔的经历. break语句 break语句会使运行的程序立刻退出包含在最内层的循环或者退出一个switch ...

  9. Elasticsearch搜索之cross_fields分析

    cross_fields类型采用了一种以词条为中心(Term-centric)的方法,这种方法和best_fields及most_fields采用的以字段为中心(Field-centric)的方法有很 ...

  10. mybatis插入List集合数据

    处女帖 今天做完一个定时任务将一个表中的数据每天统计到另外一个表中,开始是用循环的方式向数据库添加,觉得数据库可能访问压力过大,所以就使用了mybatis的foreach标签来稍微的减少压力. 首先封 ...