Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++:46---绝不重新定义继承而来的non-virtual函数

C++:46---绝不重新定义继承而来的non-virtual函数

作者头像
用户3479834
发布于 2021-02-03 06:51:30
发布于 2021-02-03 06:51:30
52400
代码可运行
举报
文章被收录于专栏:游戏开发司机游戏开发司机
运行总次数:0
代码可运行

一、看一个隐藏non-virtual函数的例子

  • 假设class D以public的方式继承于class B,代码如下:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class B {
public:
void mf();
};
class D :public B {};
int main()
{
D x;
B *pB = &x;
pB->mf();   //调用B::mf()
D *pD = &x;
pD->mf();   //调用D::mf()
return 0;
}

二、静态绑定与动态绑定

  • 关于静态绑定、动态绑定的概念之前,大家先了解下静态类型的类变量和动态类型的类变量概念和区别。
    • 静态类型的类变量:在编译时就已经知道是什么类型的了
    • 动态类型的类变量:自己所指的类型不明确,直到运行时才知道
  • 如果表达式既不是引用也不是指针,那么其就没有静态类型和动态类型的概念,因为其只能与自己类型一致的对象绑定到一起

演示案例

  • 当我们使用基类的引用(或指针)时,我们并不清楚该引用(或指针)所绑定的对象的真实类型,该对象可能是基类的对象,也可能是派生类的对象。只有在程序运行的时候我们才知道所绑定的对象的真实类型
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A {};class B:public A{};
int main(){A a;  //静态类型B b;  //静态类型A *p; //动态类型
p = &a; //p指向了ap = &b; //p又指向了breturn 0;}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A {protected:int a;public:void setA(int num) { a = num; }void cout_getA() { cout << "A" << a << endl; }};
class B :public A {public:void setA(int num) { a = num; }void cout_getA() { cout << "B" << a << endl; }};
int main(){A a;B b;a.setA(10);b.setA(20);
A *p1, *p2;p1 = &a;p2 = &b;
p1->cout_getA();p2->cout_getA();return 0;}
  • 结果解析:
    • A 10:这个比较简单,因为a的类型为A,且指针也为A,因此调用A的getA()函数
    • A 20:虽然p2指针指向的类类型为B,但是访问规则只与指针/引用的类类型有关,而与指针/引用指向的类型无关。因此b已经被视为一个A对象来看了。此处p2指针的类型为A,因此调用A的getA()函数。又因为b对象使用setA()函数将整个继承体系中的a改为了20,因此打印出来的a为20

静态绑定

  • 当我们调用non-virtual函数时,调用的函数版本与指针的类型有关
  • 例如,上面的pB指针在初始化时,将与D对象中的B对象所绑定;上面的pD指针在初始化时,将与D对象所绑定。这是静态绑定
  • 因此,pB调用的是B::mf();pD调用的是D::mf()

动态绑定

  • 当我们调用virtual函数时,调用的函数版本与指针所指的对象有关
  • 对virtual函数的调用,是在代码运行期间执行的。例如,如果上面的D::mf()是一个虚函数,那么会有:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class B {
public:
virtual void mf();
};
class D :public B {
public:
virtual void mf();
};
int main()
{
D x;
B *pB = &x;
pB->mf();   //调用D::mf()
D *pD = &x;
pD->mf();   //调用D::mf()
return 0;
}

三、为什么不建议派生类隐藏基类的non-virtual函数

  • 在条款32介绍过,public继承意味着is-a关系,条款34描述了为什么在class内声明一个non-virtual函数会为该class建立起一个不变性,凌驾其特异性。如果:
    • 我们在派生类中隐藏了基类的non-virtual函数,那么基类与派生类就会产生行为上的不一致,is-a关系就消失了
    • 如果想要表现出派生类与基类的不同,那么应该将函数声明为virtual(其中虚析构函数是一个例子)

四、总结

  • 绝对不要重新定义继承而来的non-virtual函数
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 游戏开发司机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++:47---绝不重新定义继承而来的缺省参数值
一、静态类型、动态类型 静态类型:在被声明时所采用的的类型 动态类型:目前所知对象的类型 演示案例 下面是一个继承体系 class Shape { public: enum ShapeColor { Red, Green, Blue }; virtual void draw(ShapeColor color = Red)const = 0; }; class Rectangle :public Shape { public: virtual void draw(ShapeColor color = Gr
用户3479834
2021/02/03
5150
C++:47---绝不重新定义继承而来的缺省参数值
C++进阶:详解多态(多态、虚函数、抽象类以及虚函数原理详解)
注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写(因为继承后基类的虚函数被继承后在派生类依旧保持虚函数属性)但是该种写法不规范,大家还是少用为好。
是Nero哦
2024/03/17
7050
C++进阶:详解多态(多态、虚函数、抽象类以及虚函数原理详解)
《逆袭进大厂》第二弹之C++进阶篇59问59答(超硬核干货)
先扯两句闲话,前段时间加了一个粉丝,他告诉我说他们老师在班级群里推荐了我,我当时听到都懵了。。。
拓跋阿秀
2021/03/22
2.5K0
《逆袭进大厂》第二弹之C++进阶篇59问59答(超硬核干货)
【专业技术】C++虚函数的缺省参数
编者按:缺省参数,缺省函数,缺省构造函数,如果你有些迷糊,本文可以让你把它看个清楚。呵呵。 前些日子,有个同学问我一个关于虚函数的缺省参数问题。他是从某个论坛上看到的,但是自己没想通,便来找我。现在分享一下这个问题。先看一小段代码: #include <iostream> using namespace std; class A { public: virtual void Fun(int number = 10) { cout <<
程序员互动联盟
2018/03/14
1.4K0
【C++进阶篇】多态
多态使得不同类型的对象可以通过相同的接口进行交互,而每个对象的具体行为是根据其自身类型来决定的,分为编译时多态和运行时多态。举个例子:对于普通人来说,票价全价,学生来说,票价半价,军人来说,优先买票等,指在根据不同的对象完成不同买票行为。 下面用示例代码来展现该行为(如下):
熬夜学编程的小王
2025/05/14
1140
【C++进阶篇】多态
C++析构函数定义为virtual虚函数,有什么作用?
简单的说,C++中基类采用virtual虚析构函数是为了防止内存泄漏,如果派生类中申请了内存空间,并在析构函数中对这些内存空间进行了释放。
GeekLiHua
2025/01/21
1810
C++析构函数定义为virtual虚函数,有什么作用?
C++ Virtual And Pure Virtual Explained
---- Virtual Virtual Function是成员函数,其行为在派生类中被覆盖。与非虚函数不同的是,即使没有关于类的实际类型的编译时信息,也会保留重写的行为。如果派生类使用指针或者对基类的引用进行处理,则对被覆盖的虚函数的调用将调用派生类中定义的行为。 #include <iostream> struct Base { virtual void f() { std::cout << "base\n"; } }; struct Derived : Base {
吕海峰
2018/04/03
1.1K0
解锁C++多态的魔力:灵活与高效的编码艺术(下)
继上篇解锁C++多态的魔力:灵活与高效的编码艺术(上) 多态性是面向对象编程的重要特性之一,而C++通过虚函数、继承等机制实现了这一强大的功能。多态性使得代码更加灵活和可扩展,允许不同类型的对象以统一的方式进行操作。在本篇文章中,我们将深入探讨C++中多态的实现原理、使用场景及其优劣势,并通过具体代码示例展示如何利用多态来提升代码的可维护性和复用性。
suye
2024/10/20
2160
解锁C++多态的魔力:灵活与高效的编码艺术(下)
【C++】多态
在之前我讲过OOP(面向对象编程)的三大核心思想之一———多态性(polymorphism)。我们把具有继承关系的多个类型称为多态类型,因为我们能使用这些类型的“多种形式”而无需在意他们的差别。引用或指针的静态类型与动态类型不同这一事实正是C++语言支持多态性的根本所在。
薄荷冰
2024/01/22
2510
【C++】多态
常见c和cpp面试题目汇总(一)
STL包括两部分内容:容器和算法;容器即存放数据的地方,比如array, vector,分为两类,序列式容器和关联式容器:
用户6280468
2022/03/21
1.8K0
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
本篇文章是继继承之后,博主跟大家介绍面向对象三大特性的最后一个——多态。
ephemerals__
2024/12/25
7160
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
【C++】从静态到动态:多态的诗意旅程
https://blog.csdn.net/hsy1603914691/article/details/146056477
风中的云彩
2025/04/01
2040
【C++】从静态到动态:多态的诗意旅程
C++多态虚函数动态绑定
动态绑定是将一个过程调用与相应代码链接起来的行为。是指与给定的过程调用相关联的代码,只有在运行期才可知的一种绑定,它是多态实现的具体形式。
里克贝斯
2021/05/21
1.6K0
C++多态虚函数动态绑定
【C++深度探索】全面解析多态性机制(二)
虚函数表(Virtual Function Table,VTable)是C++中实现动态多态性的一种机制。每个包含虚函数的类都有一个对应的虚函数表,用于存储该类的虚函数地址。
大耳朵土土垚
2024/07/16
1710
【C++深度探索】全面解析多态性机制(二)
【C++】模板/继承/多态
基类对象 < -派生类对象 类型从下到上的转换(可以) 派生类对象 <- 基类对象 类型从上到下的转换(不可以) 基类指针(引用)<- 派生类对象 类型从下到上的转换(可以) 派生类指针(引用)<-基类对象 类型从上到下的转换(不可以)
洁洁
2024/09/05
2710
(超级清晰易懂版)多态--C++
多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态),这里我们重点说运行时多态,编译时多态(静态多态)和运行时多态(动态多态)。编译时多态(静态多态)主要就是我们前面讲的函数重载和函数模板,他们传不同类型的参数就可以调用不同的函数,通过参数不同达到多种形态,之所以叫编译时多态,是因为他们实参传给形参的参数匹配是在编译时完成的,我们把编译时一般归为静态,运行时归为动态。 运行时多态,具体点就是去完成某个行为(函数),可以传不同的对象就会完成不同的行为,就达到多种形态。
小志biubiu
2025/02/27
1270
(超级清晰易懂版)多态--C++
【C++篇】虚境探微:多态的流动诗篇,解锁动态的艺术密码
虚函数表(Virtual Table, VTable)是 C++ 实现运行时多态的核心机制。它是一个存储虚函数指针的数组,每个包含虚函数的类都至少有一个虚表。当一个类的虚函数被调用时,程序并不是直接调用函数的地址,而是通过虚函数表间接调用。每个对象实例都会保存一个指向虚表的指针(vptr),通过 vptr,程序可以找到对象对应的虚函数实现。
半截诗
2024/10/11
2540
【C++之剑】我不允许你还不会多态
Hello,这里是kiki,今天继续更新C++部分,我们继续来扩充我们的知识面,我希望能努力把抽象繁多的知识讲的生动又通俗易懂,今天要讲的是C++三大特性的多态~
小文要打代码
2024/10/16
1310
【C++之剑】我不允许你还不会多态
从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
s1mba
2017/12/28
1.4K0
从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数、C++对象模型图
【c++】多态&&虚函数&&抽象类&&继承中的虚函数表详解
多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态
用户10925563
2024/06/04
5820
【c++】多态&&虚函数&&抽象类&&继承中的虚函数表详解
推荐阅读
相关推荐
C++:47---绝不重新定义继承而来的缺省参数值
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验