C++虚函数继承原理和用法及示例:一文带你完全掌握

背景

  • C++虚函数原理和用法及示例:一文带你完全掌握

虚函数原理

虚函数问题思考

  • 1、什么是纯虚函数?(进一步引申出抽象类)
    答:纯虚函数是指在基类中声明了虚函数,但是基类没给出实现,子类必须重写该虚函数。并且由于基类虚函数没实现,因此基类是抽象类无法实例出对象。

  • 2、虚函数语法?

    class Base {
    public:
        virtual void show() {
            std::cout << "Base show()" << std::endl;
        }
        virtual void draw() = 0;
    };
    class Derived : public Base {
    public:
        void show() override {
            std::cout << "Derived show()" << std::endl;
        }
        void draw() override {
            std::cout << "Derived draw()" << std::endl;
        }
    };
    

    如上,1、基类中通过virtual 说明是个虚函数,子类在实现时不需要带virtual ,子类通过 override说明该函数是覆盖基类的虚函数的。2、基类中未实现的函数可以通过 = 0 来说明是纯虚函数,子类必须实现。3、继承时需要指定继承方式public或者protected、private

  • 3、如果基类中不用virtual 修饰,子类重写了该函数,会怎么样?
    答:此时发生了普通函数的覆盖(override),基类函数被隐藏。但由于不是虚函数覆盖,不存在动态绑定,因此此时的覆盖无法实现多态性。例子如下:

    class Base {
    public:
        virtual void show() {
            std::cout << "Base show()" << std::endl;
        }
        void NotVir(void) {
            cout << "Base not virtual\n";
        }
    };
    class Derived : public Base {
    public:
        void show() override {
            std::cout << "Derived show()" << std::endl;
        }
        void callBaseShow() {
            Base::show(); // 显式调用基类的 show(),即使它是虚函数
        }
        void NotVir(void) {
            cout << "Derived not virtual\n";
        }
    };
    int main() {
        Base b;
        Derived d;
    	Base *p = &d;
    	
        p->NotVir();//输出:Base not virtual
        p->show();//输出:Derived show
        p = &b;
        p->NotVir();//输出:Base not virtual
        p->show();//输出:Base show
        return 0;
    }
    

    可以看出,普通函数的覆盖不能实现多态,而虚函数的覆盖可以实现多态。

  • 4、发生函数覆盖override时,通过子类域说明符调用基类函数的语法合法吗?
    答:合法。以上述 例子3 中的代码,改main函数如下:

    int main() {
        Base b;
        Derived d;
        Base *p = &d;
            
        d.show();         	// 输出: Derived show()
        d.callBaseShow(); 	// 输出: Base show()
        d.Base::show(); 	// 输出: Base show()
        d.NotVir();			// 输出: Derived not virtual
        d.Base::NotVir();	//输出:Base not virtual
    
    	p->show();         		// 输出: Derived show()
        //p->callBaseShow(); 	// 语法错误,因为p是Base类型,不知道callBaseShow存在
        p->Base::show(); 		// 输出: Base show()
        p->NotVir();			// 输出: Base not virtual
        p->Base::NotVir();		//输出:Base not virtual
        
        return 0;
    }
    

    从上述例子可以看出:1、对于子类中的新函数,基类指针无法得知更无法访问。2、对于非虚函数的覆盖,基类指针只能执行基类中的函数,无法实现动态绑定,哪怕通过域说明符也是只执行基类中的函数。

  • 5、继承方式
    答:区别如下:
    在这里插入图片描述
    并且private继承时,基类的指针不能指向子类成员。并且对象也不能访问private成员,只能类内部的代码访问。

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天城寺电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值