zoukankan      html  css  js  c++  java
  • 12-继承与多态(下)

    一.重写与重载

       

    class Parent
    	{
    	public:
    		virtual  void func()
    		{
    			cout<<" void func()"<<endl;
    		}
    		virtual void func(int i)
    		{
    			cout<<" void func(int i)"<<endl;
    		}
    		virtual void func(int i,int j)
    		{
    			cout<<" void func(int i,int j)"<<endl;
    		}
    	};
    	
    class Child:public Parent
    {
    public:
    	virtual void func(int a,int b)
    	{
    		cout<<" void func(int a,int b)"<<endl;
    	}
    	virtual void func(int i,int j,int k)
    	{
    		cout<<" void func(int i,int j,int k)"<<endl;
    	}
    };	
    

        函数重载:

               (1)必须在同一类中,也就是在同一个作用域中。

               (2) 子类无法重载父类的函数。父类同名函数被覆盖

                  如: c.func();//错误,编译只是 

               (3)重载是在编译期间依据參数类型和个数决定调用函数的

        函数重写:
                (1) 必须发生在父类与子类之间

                (2) 而且父类与子类中的函数必须有全然同样的原型。

                (3) 使用 virtual 声明之后能顾产生多态

                (4) 多态是在执行期间依据详细对象的类型决定调用函数的

        对照: 一个是在编译期间决定的,一个是在执行期间决定的,所以重载的效率还是比重写的效率高。

     

    二. 对虚函数的理解

         C++中多态的实现原理

             (1) 当类中声明虚函数时,编译器会在类中生成一个虚函数表

             (2)  虚函数表是一个存储类成员函数指针的数据结构

             (3)  虚函数表是由编译器自己主动生成与维护的

             (4)  virtual 成员函数会被编译器放入虚函数表中

             (5) 存在虚函数时。每一个对象中都有一个指向虚函数表的指针。     



     

    void run(Parent* p)
    {
    	p->func(1,2);
    }

                   通过虚函数表指针VPTR调用重写函数是在程序执行时进行的,因此须要通过寻址操作才干确        定真正的应该调用的函数。

    而普通成员函数是在编译时就确定了调用的函数。

    在效率上。虚函数            的效率要低的多。

        注意: 处于效率的考虑,没有必要把全部的成员函数都声明为虚函数。

       对象中VPTR指针什么时候被初始化的?

            (1) 对象在创建的时候由编译器对VPTR指针进行初始化。

            (2) 仅仅有当对象的构造全然结束后VPTR的指向才终于确定

            (3) 父类对象的VPTR指向父类虚函数表

            (4) 子类对象的VPTR指向子类虚函数表

    class Parent
    {
    public:
    	Parent()
    	{
    		this->func();
    	}	
    	virtual void func()
    	{
    		cout<<"virtual void Parent::func()"<<endl;
    	}
    };
    
    class Child:public Parent
    {
    public:
    	Child()
    	{
    		func();
    	}
    	void func()
    	{
    		cout<<"void Child::func()"<<endl;
    	}	
    };
    
    int main()
    {
    	Child p;  
    	p.func();
    	return 0;
    }
    



         结论: 构造函数中调用虚函数无法实现多态

    三. 纯虚函数

         面向对象的抽象类

             (1) 抽象类可用于表示现实世界中的抽象概念

             (2) 抽象类是一种仅仅能定义类型,而不能产生对象的类

             (3) 抽象类仅仅能被继承并重写相关函数

             (4) 抽象类的直接特征是纯虚函数

          说明: 纯虚函数仅仅声明函数原型,不定义函数体的虚函数。

        抽象类与纯虚函数

              (1) 抽象类不能用于定义对象

              (2) 抽象类仅仅能用于定义指针和引用

              (3) 抽象中的纯虚函数必须被子类重写

    class Shape
    {
    public:
    	virtual double area()=0;
    };

        area是纯虚函数, =0 告诉编译器这个函数有益仅仅声明不定义。

    class Shape
    {
    public:
        virtual double area() = 0;
    };
    
    class Rectangle : public Shape
    {
        double m_a;
        double m_b;
    public:
        Rectangle(double a, double b)
        {
            m_a = a;
            m_b = b;
        }
        
        double area()
        {
            return m_a * m_b;
        }
    };
    
    class Circle : public Shape
    {
        double m_r;
    public:
        Circle(double r)
        {
            m_r = r;
        }
        
        double area()
        {
            return 3.14 * m_r * m_r;
        }
    };
    
    void area(Shape* s)
    {
        cout<<s->area()<<endl;
    }
    
    int main(int argc, char *argv[])
    {
        Rectangle rect(2, 3);
        Circle circle(4);
        
        area(&rect);
        area(&circle);
     	return 0;
    }
    

    小结:

          (1) 函数重载与函数重写不同

          (2) 多态是通过虚函数实现的

          (3) 虚函数在效率上会有影响

          (4) 抽象类是通过纯虚函数实现的。     





  • 相关阅读:
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    FFmpeg解码H264及swscale缩放详解
    linux中cat more less head tail 命令区别
    C语言字符串操作总结大全(超详细)
    如何使用eclipse进行嵌入式Linux的开发
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5147632.html
Copyright © 2011-2022 走看看