• C++ 虚函数


    一段代码

    #include"stdafx.h"
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Character
    {
    public:
        void ToString()
        {
            cout << "I'm character" << endl;
        }
    };
    
    class Player : public Character
    {
    public:
        void ToString()
        {
            cout << "I'm player" << endl;
        }
    };
    
    class Npc : public Character
    {
    public:
        void ToString()
        {
            cout << "I'm npc" << endl;
        }
    };
    
    int main(void) {
        Character* character1 = new Player();
        Character* character2 = new Npc();
        character1->ToString();
        character2->ToString();
        cin.get();
        return 0;
    }

    我们期望的输出:

    I'm player
    I'm npc

    但实际输出的却是

    I'm character
    I'm character

    百度了一下了解到,如果要想实现动态多态则必须使用虚函数virtual关键字

    于是代码修改如下

    #include"stdafx.h"
    #include<iostream>
    #include<string>
    using namespace std;
    
    class Character
    {
    public:
        virtual void ToString()
        {
            cout << "I'm character" << endl;
        }
    };
    
    class Player : public Character
    {
    public:
        virtual void ToString() override
        {
            cout << "I'm player" << endl;
        }
    };
    
    class Npc : public Character
    {
    public:
        virtual void ToString() override
        {
            cout << "I'm npc" << endl;
        }
    };
    
    int main(void) {
        Character* character1 = new Player();
        Character* character2 = new Npc();
        character1->ToString();
        character2->ToString();
        cin.get();
        return 0;
    }

    这样就可以得到我们预期的结果了

    I'm player
    I'm npc

     注意,上面代码中红色字体的virutal 和 override关键字不是必须的

     其中virtual不是必须的原因在于编译器默认子类有virtual关键字;

     override可以不加是因为:c++在c++11标准之前,没有类似于Java的@override检查机制,很容易子类在重载的时候写错方法签名,override应用而生,就是表明该方法是父类需方法的重载方法,编译器会强制检查方法签名是否一致

    2018/8/12 更新

    并非实现动态多态则必须使用虚函数virtual关键字,而是在引用类型为指针或者引用时必须如此,如果是普通对象不存在这种问题,伪代码如下:

    AObject aObject;

    BObject bObject;

    aObject = bObject ,然后调用aObject.method则不需要virtual关键字也能实现多态

    AObject* aObject;

    BObject* bObject;

    aObject = bObject ,然后调用aObject->method则必须要virtual关键字才能实现多态

     2018/8/17

    1.virutal关键字在哪里加

    如果声明和实现分离,vitual关键字只能出现在声明处,否则编译时会报错“... virtual 说明符在函数定义上非法”

    如果声明和实现一体,vitual关键字可以出现在定义处,毕竟没有其他地方可加了

    2.为什么析构函数应当被声明为虚函数

    假设B为A的子类,且B增加了一个char*成员指向new分配的内存

    A* a = new B();

    delete a;

    如果析构函数不是虚函数,这是将释放a的内存,此时没有指针再指向B,B中的char*成员也再没有机会得到释放

    2018/8/18 0404

    1.什么是纯虚函数?

    一般的虚函数,形如 virutal string getName();

    结尾加上 =0 就成了纯虚函数: virtual string getName() = 0;

    2.为什么需要纯虚函数

    比如设计椭圆类和正圆类,虽然正圆貌似应该继承椭圆,但考虑到细节的时候就会发现不合适,应为椭圆有许多正圆不具备的属性,因此应该增加一个抽象类,让椭圆和正圆都继承它,在这个类里,有一些方法是基本的且可以共用的,例如move(),但是又不需要在抽象基类中实现这个方法,这时候就应该将其定义为纯虚函数。

    需要注意:

    即使声明为纯虚方法,定义中仍然可以实现它;

    含有纯虚方法的类无法被实例化;

  • 相关阅读:
    函数
    拉取代码到本地
    逻辑位运算符 以及 布尔运算符&&、||
    JS中substr与substring的区别
    ? :和!:的用法含义及es6语法...
    JS中attribute和property的区别
    并发、并行的理解
    斑鸠云商小程序记住账号和密码
    js中的foreach用法
    指针与数组
  • 原文地址:https://www.cnblogs.com/heben/p/8045339.html
Copyright © 2020-2023  润新知