zoukankan      html  css  js  c++  java
  • C++基础--虚函数和纯虚函数

    虚函数的一种重要的应用是在子类重写父类方法上,一般都是在父类中声明的时候用关键字virtual修饰。

    在C++中,一个父类的对象指针是可以指向子类的实例化对象,这个时候可以用该对象指针来访问父类的成员函数,但是访问不了子类的成员函数。如果这个父类的对象指针想要访问子类中的函数,则需要在父类中对应的函数添加virtual关键词将该函数变为虚函数,这个时候父类的对象指针就可以访问子类重写父类虚函数:

    #include <iostream>
    
    class A
    {
    public:
        virtual void prt1()
        {
            std::cout << "A1" << std::endl;
        }
        void prt2()
        {
            std::cout << "A2" << std::endl;
        }
    protected:
    private:
    };
    
    class B :public A
    {
    public:
        void prt1()
        {
            std::cout << "B1" << std::endl;
        }
        void prt2()
        {
            std::cout << "B2" << std::endl;
        }
    };
    
    
    int main(int argc, char* argv[])
    {
        A *ptrA = NULL;
        B *ptrB = new B;
        ptrA = ptrB;
        ptrA->prt1();
        ptrA->prt2();
        // delete ptrB; // 这里delete ptrB或者ptrA其中一个就可以了。
        delete ptrA;
        system("pause");
        return 0;
    }

    代码运行的结果显示如下:

    父类A声明了两个函数,prt1是虚函数,prt2是普通的成员函数,子类B继承了父类A,同样有两个函数,prt1是重写了父类的虚函数,prt2是隐藏了父类的普通话成员函数,所以当声明一个父类的对象指针并指向子类的实例化对象的时候,ptrA可以访问B的函数prt1,而访问prt2的时候只能访问父类的prt2函数。

    提到虚函数就要提一下纯虚函数,纯虚函数跟虚函数类似,也用virtual来修饰,但是多了一个是在函数最后要添加"=0"来表示纯虚函数,比如这样:

    class A
    {
    public:
    	virtual void prt0() = 0;
    	virtual void prt1()
    	{
    	    std::cout << "A1" << std::endl;
    	}
    	void prt2()
    	{
    	    std::cout << "A2" << std::endl;
    	}
    protected:
    private:
    };

    在上一个例子的类A中添加一个纯虚函数ptr0,这个时候如果类B中没有对ptr0进行重写就实例化一个对象的话,编译的时候会报错,报错类B不能进行实例化。所以要在B类中重写A的纯虚函数后B才能被实例化:

    class B :public A
    {
    public:
    	void prt0()
    	{
    	    std::cout << "B0" << std::endl;
    	}
    	void prt1()
    	{
    	    std::cout << "B1" << std::endl;
    	}
    	void prt2()
    	{
    	    std::cout << "B2" << std::endl;
    	}
    };

    这样父类的对象指针指向子类的实例化对象的时候,也还可以访问子类重写的纯虚函数的:

    int main(int argc, char* argv[])
    {
    	A *ptrA = NULL;
    	B *ptrB = new B;
    	ptrA = ptrB;
    	ptrA->prt0();
    	ptrA->prt1();
    	ptrA->prt2();
    	//delete ptrB;
    	delete ptrA;
    	system("pause");
    	return 0;
    }

    结果显示如下:

    所以纯虚函数的总结如下:

    • 父类声明纯虚函数的时候在函数最后添加"=0",这个时候父类变成抽象类,抽象类不能被实例化;

    • 子类继承重写抽象类的纯虚函数后子类才可以被实例化,并且在声明的时候不需要virtual修饰,但要与被重写的纯虚函数的函数名、参数列表、返回值完全一致,如果返回值则需要是协变的情况,否则会提示重写虚函数返回类型有差异,且不是来自“A::prt0”的协变

    • 抽象类可以有声明为一个指针指向子类的实例化对象,这个时候可以访问被子类重写的虚函数和纯虚函数,但是普通函数不行。

    • 纯虚函数的作用可以说是“只提供申明,没有实现”,是约束子类的接口的方法。

     

    月是情人和鬼的魂魄,

    月色冰冰燃一盏青焰的长明灯

    中元夜,鬼也醒着,人也醒着

    人在桥上怔怔地出神

    上善若水,为而不争。
  • 相关阅读:
    vue+element ui 实现菜单无限极菜单
    DOM事件绑定原理和传播机制
    数组和对象的深浅克隆
    new源码分析和Object.create的重写
    原型和原型链的学习
    4.3 模型参数的延后初始化
    4.2 模型参数的访问、初始化和共享
    CSAPP Float Point
    4.1 模型构造
    3.16 实战Kaggle比赛:房价预测
  • 原文地址:https://www.cnblogs.com/Bearoom/p/11721759.html
Copyright © 2011-2022 走看看