精华内容
下载资源
问答
  • 基类指针、虚函数、多态性、纯虚函数、虚析构 虚函数:https://blog.csdn.net/samkieth/article/details/49737757 C++为什么要用虚函数:https://blog.csdn.net/noricky/article/details/...

     

    3-8 基类指针、虚纯虚函数、多态性、虚析构

    虚函数:https://blog.csdn.net/samkieth/article/details/49737757

    C++为什么要用虚函数:https://blog.csdn.net/noricky/article/details/80051219

    一、基类指针、派生类指针

    父类指针可以new一个子类对象

    //Human.h
    class Human{
    public:
        Human();
        void eat();
    };
     
    //Human.cpp
    Human::Human(){
        cout << "父类Human" << endl;
    }
     
    Human::eat(){
        cout << "父类eat" << endl;
    }
     
    //---------------------------------------------------------------------
    //Man.h
    class Man: public Human{
    public:
        Man();
        void eat();
    };
     
    //Man.cpp
    Man::Man(){
        cout << "子类Man" << endl;
    }
     
    void Man::eat(){
        cout << "Man:eat" << endl;
    }
     
    int main(){
        Human *phuman = new Man();
        phuman -> eat();  //调用了父类Human的eat函数。因为phuman 父类指针。
     
    }
    Human *phuman = new Man; //父类的指针指向了一个new出来的子类对象。
    phuman->func_human(); //父类指针可以调用父类的成员函数。
    phuman->func_man(); //不可以,虽然new子类对象,但是父类指针无法调用子类的成员函数。
    
    

    既然父类指针没办法调用子类成员函数,那么为什么要让父类指针可以指向子类对象?其实我们可以通过一些方法调用父类及各个子类的函数。

    如果我们想要通过一个父类指针调用父类、子类中的同名同参函数的化,那么对这个函数是有要求的:在父类中必须在声明这个函数时在函数之前加 virtual ,声明成虚函数(建议在子类中也加上virtual,方便阅读)。

    二、虚函数

    //Human.h
    class Human{
    public:
        Human();
        virtual void eat();
    };
     
    //Human.cpp
    Human::Human(){
        cout << "父类Human" << endl;
    }
     
    void Human::eat(){
        cout << "父类eat" << endl;
    }
     
    //---------------------------------------------------------------------
    //Man.h
    class Man: public Human{
    public:
        Man();
        virtual void eat();
    };
     
    //Man.cpp
    Man::Man(){
        cout << "子类Man" << endl;
    }
     
    void Man::eat(){
        cout << "Man:eat" << endl;
    }
     
    //----------------------------------------------------------------------
    //Woman.h
    class Woman: public Human{
    public:
        Woman();
        virtual void eat() override;
    };
     
    //Woman.cpp
    Woman::Woman(){
        cout << "子类Woman" << endl;
    }
     
    void Woman::eat(){
        cout << "Woman:eat" << endl;
    }
     
    int main(){
        Human *phuman = new Man();
        phuman->eat();  //调用的时Man中的eat函数
        phuman->Human::eat(); //通过这种方式可以调用父类中的eat函数
        delete phuman;
     
        Human *phuman = new Woman();
        phuman->eat();  //调用的时Woman中的eat函数
        delete phuman;
     
        Human *phuman = new Human();
        phuman->eat();  //调用的时Human中的eat函数
        delete phuman;
    }

    有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数?

    有解决方案,这个对象指针必须是一个父类类型,我们如果想通过一个父类指针调用父类、子类中的同名函数的话,这个函数是有要求的

    在父类中,eat函数声明之前必须要加virtual声明eat()函数为虚函数。

    一旦某个函数被声明为虚函数,那么所有派生类(子类)中eat()函数都是虚函数。

    为了避免你在子类中写错虚函数,在C++11中,你可以在函数声明中增加一个override关键字,这个关键字用在子类中,而且是虚函数专用。

    override就是用来说明派生类中的虚函数,你用了这个关键字之后,编译器就会认为你这个eat是覆盖了父类中的同名函数(只有虚函数才存在子类可以覆盖父类中同名函数的问题),那么编译器就会在父类中找同名的虚函数,如果没找到,编译器就会报错,如果你不小心在子类中把虚函数写错了名字,写错了参数,编译器能够帮你进行纠错

    final也是虚函数专用,用在父类中,如果我们在父类的函数声明中加了final,那么任何尝试覆盖在函数的操作都会引发错误。

     

    调用虚函数执行的是“动态绑定”。动态表示我们程序运行的时候才能知道调用了那个子类的中的eat()虚函数。

    动态的绑定到Men上去,还是Women上去,取决于new的Men还是Women;

    动态绑定:运行的时候才决定你的phuman对象绑定到那个eat()函数上运行。

    三、多态性

    多态性只是针对虚函数来说的;

    多态性:体现在具有继承关系的父类和子类之间,子类重新定义(重写)父类的成员函数eat(),同时父类把这个eat()函数声明为virtual虚函数;

    通过父类的指针,只有到了程序运行时期,找到动态绑定到父类指针上的对象,这个对象有可能是某个子类对象,也可能是父类对象;

    然后系统内部实际上是要查找一个虚函数表,找到函数eat()的入口地址,从而调用父类或子类的eat()函数,这就是运行时的多态性。

    四、纯虚函数

    纯虚函数是在基类中声明的函数,但是他在基类中没有定义,但是要求任何派生类都要定义该虚函数自己的实现方法;

    基类中实现纯虚函数的方法使在函数原型后面增加 =0;

    //Human.h
    class Human{
    public:
        Human();
        virtual void eat() =0; //定义纯虚函数
    };
     
    //Human.cpp
    Human::Human(){
        cout << "父类Human" << endl;
    }
     

    一旦一个类中有纯虚函数,那么你就不能生成这个类的对象了;

    抽象类不能用来生成对象,主要目的是用来同意管理子类对象;

    (1)纯虚函数的类叫做抽象类,不能用来生成该类对象,主要用于当做基类来生成子类用的;

    (2)子类必须要实现该基类中定义纯虚函数;

    五、基类的析构函数一般写成虚函数(虚析构函数)

    //Human.h
    class Human{
    public:
        Human();
        ~Human();
    };
     
    //Human.cpp
    Human::Human(){
        cout << "父类Human" << endl;
    }
     
    Human::~Human(){
        cout << "父类~Human()" << endl;
    }
     
    //---------------------------------------------------------------------
    //Man.h
    class Man: public Human{
    public:
        Man();
        ~Man();
        void say();
    };
     
    //Man.cpp
    Man::Man(){
        cout << "子类Man" << endl;
    }
     
    ~Man(){
        cout << "子类~Man()" << endl;
    }
     
    void Man::say(){
        cout << "say()" << endl;
    }
     
    //--------------------------------------------------------------------
    int main(){
        Man *pman = new Man(); //调用 Human() Man()
        delete pman; //调用 ~Man() ~Human()
        
        Human *phuman = new Man(); //调用 Human() Man()
        delete phuman; //只调用了 ~Human()
     
        phuman->say(); //报错,因为基类中没有say(),基类指针无法指向子类中基类没有的成员函数
    }

    用基类指针new子类的对象,在delete的时候,系统不会调用派生类的析构函数,存在问题;

    解决方案:将基类的析构函数声明为虚析构函数;

    在public继承中,基类对派生类及其对象的操作,只能影响那些从基类继承下来的成员,如果想要用基类对非继承的成员进行操作,则要把基类的这个函数定义为虚函数,析构函数也为虚函数,基类中的析构函数的虚属性也会被派生类继承,即派生类的析构函数也为虚函数。

    Human这个类中的析构函数就要声明为virtual的,也就是说C++11中为了获得运行时多态,所调用的成员必须是virtual的。

    如果一个类想要做基类,我们必须将类的析构函数声明为virtual虚函数;

    只要基类中的析构函数为虚函数,就能保证我们delete基类指针时能够运行正确,不会出现内存泄漏。

    虚函数会增加内存开销,类里面定义虚函数,编译器就会给这个类增加虚函数表,在这个表里存放虚函数的指针

     

    本节案例:

    // Human.h
    // 头文件防卫式声明
    #ifndef __HUMAN__
    #define __HUMAN__
    
    #include "stdafx.h"
    class Human
    {
    public:
        Human();
        virtual ~Human();
    
    public:
        virtual void eat();
        virtual void eat2() = 0;
    };
    
    #endif
    
    // Human.cpp
    #include "stdafx.h"
    #include "Human.h"
    #include <iostream>
    
    Human::Human()
    {
        std::cout << "调用了Human::Human()" << std::endl;
    }
    
    void Human::eat()
    {
        std::cout << "人类喜欢吃各种美食" << std::endl;
    }
    
    Human::~Human()
    {
        std::cout << "调用了Human::~Human()" << std::endl;
    }
    
    // Men.h
    #ifndef __MEN__
    #define  __MEN__
    
    #include "stdafx.h"
    #include "Human.h"
    
    class Men : public Human
    {
    public:
        Men();
        ~Men();
    public:
        virtual void eat() override;
        virtual void eat2();
    };
    
    #endif
    
    // Men.cpp
    #include "stdafx.h"
    #include "Men.h"
    #include <iostream>
    
    void Men::eat()
    {
        std::cout << "男人喜欢吃米饭" << std::endl;
    }
    
    void  Men::eat2()
    {
        std::cout << "男人喜欢吃米饭2" << std::endl;
    }
    
    Men::Men()
    {
        std::cout << "调用了Men::Men()" << std::endl;
    }
    
    Men::~Men()
    {
        std::cout << "调用了Men::~Men()" << std::endl;
    }
    
    // Women.h
    #ifndef __WOMEN__
    #define  __WOMEN__
    #include "stdafx.h"
    #include "Human.h"
    class Women : public Human
    {
    public:
        Women();
        ~Women();
    
    public:
        virtual void eat() override;
        virtual void eat2() override;
    };
    
    #endif
    
    // Women.cpp
    #include "stdafx.h"
    #include "Women.h"
    #include <iostream>
    
    Women::Women()
    {
        std::cout << "调用了Women::Women()" << std::endl;
    }
    
    Women::~Women()
    {
        std::cout << "调用了Women::~Women()" << std::endl;
    }
    
    void Women::eat()
    {
        std::cout << "女人喜欢吃面食" << std::endl;
    }
    
    void Women::eat2()
    {
        std::cout << "女人喜欢吃面食2" << std::endl;
    }
    
    // main.cpp
    // Project3.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include "Human.h"
    #include "Men.h"
    #include "Women.h"
    
    using namespace std;
    
    int main()
    {
        Human *phuman = new Men;
        phuman->eat();  // 男人喜欢吃米饭
        delete phuman;
    
        phuman = new Women;
        phuman->eat(); // 女人喜欢吃面食
        delete phuman;
    
        //phuman = new Human;
        //phuman->eat(); // 人类喜欢吃各种美食
        //delete phuman;
        phuman = new Men;
        phuman->eat2();  // 男人喜欢吃米饭
        delete phuman;
    
        phuman = new Women;
        phuman->eat2(); // 女人喜欢吃面食
        delete phuman;
    
        //Men men;
        Men *pmen = new Men;
        delete pmen;
    
        Human *phuman1 = new Men;
        delete phuman1;  // 没有执行子类的析构函数
    
        return 0;
    }

     

     

     

    展开全文
  • 待补充

    待补充

    //虚函数  override final default delete 在C++11新增
    struct Base
    {
    public:
    	virtual void foo() final {};//标注final
    
    };
    
    //子类继承父类函数重载
    class SubClass final :public Base
    {
    public:
    	// override显示的告诉这个是虚函数,在后期维护的时候可以方便看到,用于提醒  
    	void foo() override{};//b报错
    };
    
    // final 如果在类后面标注告诉编译器,这是最后一个类,无法在被继承的类
    //final 在虚函数后面,告诉派生类无法在重载这个类的虚函数了
    class subclass2 :public SubClass   //报错
    {
    public:
    };
    //default
    class Base01
    {
    public:
    	Base01() = default;//保留默认构造析构拷贝函数
    	Base01(int i)  //如何没有default 则默认没有无参构造
    	{
    	
    	}
    };
    //delete
    class Base02
    {
    public:
    	Base02() = delete;//禁止编译器参数默认构造
    	Base02(int i)  
    	{
    
    	}
    };
    int main()
    {
    	return 0;
    }

     

    展开全文
  • 一:基类指针与子类指针 在这里插入代码片 二:虚函数 ...c++11引入的override与final关键字在虚函数中的应用。 说明:override只能在子类中使用,而final只能在父类中使用,并且是只能用在虚函数上。 ...

    一:基类指针与子类指针

    #include "pch.h"
    #include <iostream>
    using namespace std;
    
    class human
    {
    public:
    	void eat() { cout << "各种粮食" << endl; };
    };
    
    class man :public human
    {
    public:
    	void eat() { cout << "面食" << endl; };
    };
    
    class woman :public human
    {
    public:
    	void eat() { cout << "米饭" << endl; };
    };
    int main()
    {
    	//没问题,
    	human *phuman = new human; //基类指针
    	man   *pman = new man; //子类指针
    	woman *pwoman = new woman; //子类指针
    
    
    	//新玩法,一个父类指针可以new一个子类对象
    	human *phuman1 = new man; 
    	phuman1->eat();//虽然是new子类对象,但是,这里调用的还是父类中的eat函数。
    
    	/*
    	说明:
    	1:一个父类指针可以new一个对象,是因为子类中含有的子对象包括父类,
    		但是,一个子类new一个父类对象就不可以了。
    	2:我要怎么样用一个父类指针就可以调用子类中的eat函数呢?
    	*/
    	
    	return 0;
    }
    

    二:虚函数

    /*一:抛出了一个问题,即如何用一个父类指针去调用子类里的eat函数?有办法吗?有,那就是引入虚函数,这样就可以用一个父类指针即调用父类的eat函数又可以调用子类的eat函数了*/
    #include "pch.h"
    #include <iostream>
    using namespace std;
    
    class human
    {
    public:
    	virtual void eat() { cout << "各种粮食" << endl; };
    	/*
    	在函数声明前加上virtual,这个函数就成了虚函数了,注意是声明,不是定义,
    	要是声明和定义放在一块,也可以加上virtual,就像上面那样。
    	在类外实现时,不用加virtual
    	*/
    };
    
    class man :public human
    {
    public:
    	void eat() { cout << "面食" << endl; };
    };
    
    class woman :public human
    {
    public:
    	void eat() { cout << "米饭" << endl; };
    };
    int main()
    {
    	human *phuman = new man;
    	phuman->eat(); //这样调用的就是子类的eat函数了
    
    	//那我怎么调用父类里的eat函数?
    	human *phuman1 = new man;
    	phuman1->human::eat();//ok,显示调用的父类的eat函数	
    	/*
    		eat函数。如果在类中中加了virtual,那么子类中就不用加上这个关键字了
    		这样,在调用eat函数的时候,执行的就是动态绑定了,即new什么就调用谁
    	*/
    	return 0;
    }
    

    三:override与final关键字
    c++11引入的override与final关键字在虚函数中的应用。

    说明:override只能在子类中使用,而final只能在父类中使用,并且是只能用在虚函数上(或者是用在基类上,用来阻止派生类的继承)。

    final与override相对,在父类的虚函数加上它以后,就是说,不要希望在子类中去覆盖父类的eat函数,用了final以后,再用override就不可以了。或者说是用了final以后,子类中就不能在写eat函数了。

    #include "pch.h"
    #include <iostream>
    using namespace std;
    
    class human
    {
    public:
    	virtual void eat() { cout << "各种粮食" << endl; };
    	/*
    	在函数声明前加上virtual,这个函数就成了虚函数了,注意是声明,不是定义,
    	要是声明和定义放在一块,也可以加上virtual,就像上面那样。
    	在类外实现时,不用加virtual
    	*/
    
    	/*
     virtual void eat() final; 这样写,后面子类就不能写eat函数了。
       */
    };
    
    class man :public human
    {
    public:
    	void eat() { cout << "面食" << endl; };
    };
    
    class woman :public human
    {
    public:
    	void eat(int a) override{ cout << "米饭" << endl; }; /*错误,加上override的意思是说,要覆盖父类中的同名同参的虚函数函数,也就是说,为了防止我们写错参数个数或者函数名,那么你加上override以后,编译器就会对你提示错误,比如这里报错的原因就是因为,父类的虚函数中,没有参数为int的eat函数*/
    };
    int main()
    {
    	human *phuman = new man;
    	phuman->eat(); //这样调用的就是子类的eat函数了
    
    	//那我怎么调用父类里的eat函数?
    	human *phuman1 = new man;
    	phuman1->human::eat();//ok,显示调用的父类的eat函数	
    	/*
    		eat函数。如果在类中中加了virtual,那么子类中就不用加上这个关键字了
    		这样,在调用eat函数的时候,执行的就是动态绑定了,即new什么就调用谁
    	*/
    	return 0;
    }
    
    

    附:有那些函数不能声明为虚函数:
    https://www.cnblogs.com/dingou/p/11627596.html

    展开全文
  • 公有继承包含两部分:一是 “函数接口” (interface),二是 “函数实现” (implementation) 如 Shape 类中,三个成员函数,对应三种继承方式: class Shape { public: virtual void Draw() const = 0; // 1) 纯虚...

    转载自
    https://www.cnblogs.com/xinxue/p/5471708.html

    1 公有继承
    公有继承包含两部分:一是 “函数接口” (interface),二是 “函数实现” (implementation)

    如 Shape 类中,三个成员函数,对应三种继承方式:

    class Shape {
    public:
        virtual void Draw() const = 0;    // 1) 纯虚函数
        virtual void Error(const string& msg);  // 2) 普通虚函数
        int ObjectID() const;  // 3) 非虚函数
    };
    
    class Rectangle: public Shape { ... };
    class Ellipse: public Shape { ... };
    

    1.1 纯虚函数 (pure virtual)
    纯虚函数,继承的是基类中,成员函数的接口,且要在派生类中,重写成员函数的实现

    Shape *ps1 = new Rectangle;
    ps1->Draw(); // calls Rectangle::Draw
    
    Shape *ps2 = new Ellipse;
    ps2->Draw(); // calls Ellipse::Draw
    

    调用基类的 Draw(),须加 类作用域操作符 ::

    ps1->Shape::Draw(); // calls Shape::draw
    

    1.2 普通虚函数
    普通虚函数,会在基类中,定义一个缺省的实现 (default implementation),表示继承的是基类成员函数接口和缺省实现,由派生类选择是否重写该函数。

    实际上,允许普通虚函数 同时继承接口和缺省实现是危险的。 如下, ModelA 和 ModelB 是 Airplane 的两种飞机类型,且二者的飞行方式完全相同

    class Airplane {
    public:
        virtual void Fly(const string& destination);
    };
    class ModelA: public Airplane { ... };
    class ModelB: public Airplane { ... };
    

    这是典型的面向对象设计,两个类共享一个特性 – Fly,则 Fly 可在基类中实现,并由两个派生类继承之

    现增加另一个飞机型号 ModelC,其飞行方式与 ModelA,ModelB 不相同,如果不小心忘记在 ModelC 中重写新的 Fly 函数

    class ModelC: public Airplane {
        ... // no fly function is declared
    };
    

    则调用 ModelC 中的 fly 函数,就是调用 Airplane::Fly,但是 ModelC 的飞行方式和缺省的并不相同

    Airplane *pa = new ModelC;
    pa->Fly(Qingdao); // calls Airplane::fly!
    

    即前面所说的,普通虚函数同时继承接口和缺省实现是危险的,最好是基类中实现缺省行为 (behavior),但只有在派生类要求时才提供该缺省行为

    1.2.1 方法一
    一种方法是 纯虚函数 + 缺省实现,因为是纯虚函数,所以只有接口被继承,其缺省的实现不会被继承。派生类要想使用该缺省的实现,必须显式的调用

    class Airplane {
    public:
        virtual void Fly(const string& destination) = 0;
    };
    
    void Airplane::Fly(const string& destination)
    { 
        // a pure virtual function default code for flying an airplane to the given destination
    }
    
    class ModelA: public Airplane {
    public:
        virtual void Fly(const string& destination) { Airplane::Fly(destination); }
    };
    

    这样在派生类 ModelC 中,即使一不小心忘记重写 Fly 函数,也不会调用 Airplane 的缺省实现

    class ModelC: public Airplane {
    public:
        virtual void Fly(const string& destination);
    };
    
    void ModelC::Fly(const string& destination)
    {
        // code for flying a ModelC airplane to the given destination
    }
    

    1.2.2 方法二
    可以看到,上面问题的关键就在于,一不小心在派生类 ModelC 中忘记重写 fly 函数,C++11 中使用关键字 override,可以避免这样的“一不小心”

    1.3 非虚函数
    非虚成员函数没有 virtual 关键字,表示派生类不但继承了接口,而且继承了一个强制实现 (mandatory implementation)

    既然继承了一个强制的实现,则在派生类中,无须重新定义 (redefine) 继承自基类的成员函数,如下:

    使用指针调用 ObjectID 函数,则都是调用的 Shape::ObjectID()

    Rectangel rc; // rc is an object of type Rectangle
    
    Shape *pB = &rc; // get pointer to rc
    pB->ObjectID(); // call ObjectID() through pointer
    
    Rectangle *pD = &rc; // get pointer to rc
    pD->ObjectID(); // call ObjectID() through pointer
    

    如果在派生类中重新定义了继承自基类的成员函数 ObjectID 呢?

    class Rectangel : public Shape {
    public:
        int ObjectID() const; // hides Shape::ObjectID
    };
    
    pB->ObjectID(); // calls Shape::ObjectID()
    pD->ObjectID(); // calls Rectagle::ObjectID()
    

    此时,派生类中重新定义的成员函数会 “隐藏” (hide) 继承自基类的成员函数

    这是因为非虚函数是 “静态绑定” 的,pB 被声明的是 Shape* 类型的指针,则通过 pB 调用的非虚函数都是基类中的,既使 pB 指向的是派生类

    与“静态绑定”相对的是虚函数的“动态绑定”,即无论 pB 被声明为 Shape* 还是 Rectangle* 类型,其调用的虚函数取决于 pB 实际指向的对象类型

    2 重写 (override)
    在 1.2.2 中提到 override 关键字,可以避免派生类中忘记重写虚函数的错误

    下面以重写虚函数时,容易犯的四个错误为例,详细阐述之

    class Base {
    public:
        virtual void mf1() const;
        virtual void mf2(int x);
        virtual void mf3() &;
        void mf4() const;    // is not declared virtual in Base
    };
    
    class Derived: public Base {
    public:
        virtual void mf1();        // declared const in Base, but not in Derived.
        virtual void mf2(unsigned int x);    // takes an int in Base, but an unsigned int in Derived
        virtual void mf3() &&;    // is lvalue-qualified in Base, but rvalue-qualified in Derived.
        void mf4() const;        
    };
    

    在派生类中,重写 (override) 继承自基类成员函数的实现 (implementation) 时,要满足如下条件:

    一虚:基类中,成员函数声明为虚拟的 (virtual)

    二容:基类和派生类中,成员函数的返回类型和异常规格 (exception specification) 必须兼容

    四同:基类和派生类中,成员函数名、形参类型、常量属性 (constness) 和 引用限定符 (reference qualifier) 必须完全相同

    如此多的限制条件,导致了虚函数重写如上述代码,极容易因为一个不小心而出错

    C++11 中的 override 关键字,可以显式的在派生类中声明,哪些成员函数需要被重写,如果没被重写,则编译器会报错。

    class Derived: public Base {
    public:
        virtual void mf1() override;
        virtual void mf2(unsigned int x) override;
        virtual void mf3() && override;
        virtual void mf4() const override;
    };
    

    这样,即使不小心漏写了虚函数重写的某个苛刻条件,也可以通过编译器的报错,快速改正错误

    class Derived: public Base {
    public:
        virtual void mf1() const override;  // adding "virtual" is OK, but not necessary
        virtual void mf2(int x) override;
        void mf3() & override;
        void mf4() const override; 
    }; 
    

    小结:

    1. 公有继承

    纯虚函数 => 继承的是:接口 (interface)

    普通虚函数 => 继承的是:接口 + 缺省实现 (default implementation)

    非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)

    1. 不要重新定义一个继承自基类的非虚函数 (never redefine an inherited non-virtual function)

    2. 在声明需要重写的函数后,加关键字 override

    展开全文
  • C++ 虚函数看这一篇 目的是用一个指针,既能调用父类的函数,又能调用子类的函数(同名同参同返回值(返回值可以有点小差别,不是相互转换类型))。 这个对象指针,它的类型必须是父类类型。 父类成员函数必须声明...
  • 3. 重载函数的调用是以所传递参数的差别作为调用不同函数的依据,虚函数是根据对象动态类型的不同去调用不同的类的虚函数; 4. 重载函数在编译时表现出多态性,而虚函数在运行时便显出多态功能。
  • C++多态--虚函数virtual及override

    万次阅读 多人点赞 2017-08-16 23:35:52
    C++多态(polymorphism)是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。 最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,...
  • C++11新特性之虚函数override指示符

    千次阅读 2017-09-03 23:24:53
    2. 下面Demo中,Student类继承于People类(public公有继承),在People类中对PrintInf函数进行了虚函数的声明;为了实现多态(多态的3个条件:有继承、虚函数重写(覆盖)、有父类指针或引用指向子类对象);在父类...
  • 虚表指针5.object slicing与虚函数6.overload、override、overwrite 1.多态 多态性是面向对象程序设计的重要特征之一 多态性是指发出同样的消息被不同类型的对象接收时,有可能导致完全不同的行为 (1)调用同名的...
  • C++笔记 15.2 虚函数

    2020-09-05 19:53:17
    primer C++笔记 虚函数 派生类中的虚函数 override final 虚函数与默认实参 回避虚函数的机制
  • 【c++】虚函数描述符override

    千次阅读 2014-05-10 12:45:25
    C++11中为了帮助程序员写继承结构复杂的类型,引入了虚函数描述符override 重载虚函数 就加上关键字override 这样编译器可以辅助检查是不是正确重载,如果没加这个关键字 也没什么严重的error 只是少了编译器检查的...
  • override:对虚函数进行重写的函数 final与override 假设声明一个基类的指针,它可以根据指向的对象类型动态的绑定对应的函数 虚函数的默认实参 如果我们通过基类的引用或指针调用函数,则使用基类中定义的默认实参 ...
  • 继承的是:接口 (interface)普通虚函数 => 继承的是:接口 + 缺省实现 (default implementation)非虚成员函数 =>继承的是:接口 + 强制实现 (mandatory implementation)2) 不要重新定义一个继承自基类的非...
  • 初识虚函数 用virtual关键字说明的函数; 虚函数是实现运行时多态性基础; C++中的虚函数是动态绑定的函数; 虚函数必须是非静态的成员函数,虚函数经过派生之后,就可以实现运行过程中的多态; 一般成员函数可以...
  • #include<iostream> using namespace std;...//对于虚函数 final 当前虚函数到此为止,子类不能对这个虚函数进行重写。 class Base { public: virtual void foo() final {} ; Base(int n) { /...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,381
精华内容 552
热门标签
关键字:

虚函数override