时间:2021-05-20
基础理解和demo
普通的继承
#include<iostream>class Parent {public: void print() { std::cout << "Parent" << std::endl; }};class Child : Parent {public: void print() { std::cout << "Child" << std::endl; }};int main() { Child c; c.print(); return 0;}输出结果为 "Child"
但是如果是 "父类的指针指向子类的对象" 这种情况下, 使用这个父类的指针去调用被重写的方法呢, 结果会是什么呢? 从语法的本质上讲, 子类对象的内存前半部分就是父类, 因为可以将子类对象的指针直接转化为父类。
#include<iostream>class Parent {public: void print() { std::cout << "Parent" << std::endl; }};// 注意这里必须是 public Parent// 不然会报错 cannot cast 'Child' to its private base class 'Parent'class Child : public Parent {public: void print() { std::cout << "Child" << std::endl; }};int main() { Parent* p = new Child(); p->print(); return 0;}这个时候输出的是 "Parent"。
所以, 当一个成员函数需要被子类重写, 那么必须将其声明为virtual, 也就是 虚函数 , 注意, 子类覆写的方法的virtual关键字会自动继承而来, 可以显示地写或者不写(建议还是写上)。
这样修改完就没问题了:
#include<iostream>class Parent {public: virtual void print() { std::cout << "Parent" << std::endl; }};class Child : public Parent {public: virtual void print() { std::cout << "Child" << std::endl; }};int main() { Parent* p = new Child(); p->print(); return 0;}加深理解
Virtual 关键字的一个重要概念 "只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用" , 也就是说, 基类的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的。
举个例子
#include <iostream.h>class Base{public:virtual void f(float x){ cout << "Base::f(float) " << x << endl; }void g(float x){ cout << "Base::g(float) " << x << endl; }void h(float x){ cout << "Base::h(float) " << x << endl; }}; class Derived : public Base{public:virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }void g(int x){ cout << "Derived::g(int) " << x << endl; }void h(float x){ cout << "Derived::h(float) " << x << endl; }}; void main(void){Derived d;Base *pb = &d;Derived *pd = &d;// Good : behavior depends solely on type of the objectpb->f(3.14f); // Derived::f(float) 3.14pd->f(3.14f); // Derived::f(float) 3.14// Bad : behavior depends on type of the pointerpb->g(3.14f); // Base::g(float) 3.14pd->g(3.14f); // Derived::g(int) 3 (surprise!)// Bad : behavior depends on type of the pointerpb->h(3.14f); // Base::h(float) 3.14 (surprise!)pd->h(3.14f); // Derived::h(float) 3.14}粘贴这个博客的一段话, 表达的就是这个意思:
bp 和dp 指向同一地址,按理说运行结果应该是相同的,而事实上运行结果不同,所以他把原因归结为C++的隐藏规则,其实这一观点是错的。决定bp和dp调用函数运行结果的不是他们指向的地址,而是他们的指针类型。 “只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用”(C++ Primer 3rd Edition)。pb是基类指针,pd是派生类指针,pd的所有函数调用都只是调用自己的函数,和多态性无关,所以pd的所有函数调用的结果都输出Derived::是完全正常的;pb的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的,所以有virtual的f函数调用输出Derived::,其它两个没有virtual则还是输出Base::很正常啊 ,nothing surprise! 所以并没有所谓的隐藏规则,虽然《高质量C++/C 编程指南》是本很不错的书,可大家不要迷信哦。记住“只有在通过基类指针或引用间接指向派生类子类型时多态性才会起作用”。
到此这篇关于C++ Virtual关键字的具体使用的文章就介绍到这了,更多相关C++ Virtual关键字内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
说点对这几个容易混淆的词的理解:1、c++中的virtual方法的virtual关键字主要是防止继承中重复继承父类的同一个方法而设置的标识。2、virtual与
在C++中有一个概念是虚成员,那么什么是虚成员呢?在C++中“虚成员”就是其声明中在返回类型前带有关键字“virtual&r
C++子类父类成员函数的覆盖和隐藏实例详解函数的覆盖覆盖发生的条件:(1)基类必须是虚函数(使用virtual关键字来进行声明)(2)发生覆盖的两个函数分别位于
Java的static关键字和C/C++语言的关键字有所不同:一旦在Java里使用了static关键字,那么这样的内容不再属于对象自己,而是属于类本身的,所以凡
本文实例分析了asp.net中virtual和abstract的区别,分享给大家供大家参考。具体分析如下:一、Virtual方法(虚方法)virtual关键字用