之前只注意过访问控制与继承的关系,这边不多说,今天看到代码看到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. 老李分享:android app自动化测试工具合集

    老李分享:android app自动化测试工具合集   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨 ...

  2. JAVA 发送邮件代码---发送HTML内容

    依赖包:mail.jar JAR链接地址: http://pan.baidu.com/s/1o8LNl0Y 密码: ja52 package com.dava; import java.util.Pr ...

  3. 手机交互应用服务(状态栏提示信息Notifications)

    官方的一个简单的例子: NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon ...

  4. TypeScript入门-函数

    ▓▓▓▓▓▓ 大致介绍 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用.TypeScript中的函数也包括JavaScript中最常见的两种函数 functio ...

  5. 20170410 --- Linux备课资料 --- vim的使用

    首先我们要了解一下什么是vim? -----> vim是从vi发展出来的一个文本编辑器. 那问题又来了,什么是vi呢? ------> vi 是Unix like (可以理解为linux) ...

  6. JavaScript高级内容:原型链、继承、执行上下文、作用域链、闭包

    了解这些问题,我先一步步来看,先从基础说起,然后引出这些概念. 本文只用实例验证结果,并做简要说明,给大家增加些印象,因为单独一项拿出来都需要大篇幅讲解. 1.值类型 & 引用类型 funct ...

  7. Linux SvN操作

    Linux svn管理工具的12个命令实践 2010-08-25 10:50 佚名 icycling.cublog.cn 字号:T | T 目前,绝大多数开源软件都使用svn作为代码版本管理软件.本文 ...

  8. Log4j配置文件内容详解

    .Log4j的优点 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送地:我们也可以控制每一条日志的输出格式:通过定义每一条日志信息的级别,我们能够更加细致地控 ...

  9. 时间同步方法及几个可用的NTP服务器地址

    大家都知道计算机电脑的时间是由一块电池供电保持的,而且准确度比较差经常出现走时不准的时候.通过互联网络上发布的一些公用网络时间服务器NTP server,就可以实现自动.定期的同步本机标准时间. 依靠 ...

  10. Named function expressions demystified

    Introduction Surprisingly, a topic of named function expressions doesn't seem to be covered well eno ...