欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C++虚函数

最编程 2024-04-14 10:46:34
...
武汉源创会回归,4月20聊聊大模型”
    对virtual关键字的解析


    使用virtual关键字修饰的函数,在通过类对象而被调用的时候,与类的一般函数一样正常被调用。只有在通过基类
指针或引用间接指向派生类子类型时,被调用函数才会被解析为动态类型,多态性才会起作用。而使用基类对象并不会留派生类的类型身份。
在使用时,只需在类的声明中用virtual关键字指定虚函数即可,在类的实现中无需再次标明。
下面分析几种情况:
1.基类中未用virtual修饰的函数在子类中被重写,函数声明完全相同。

   如:

class parent{
           public: 
               void drink(){ 
                   cout<<"parent drink()"<<endl; 
              } 
        }; 
        class child:public parent{ 
             public: 
                  void drink(){ 
                       cout<<"child drink()"<<endl; 
                  } 
        };
   使用基类指针指向子类对象调用drink函数,调用的是基类的drink函数;
   输出:
    parent drink()
2.基类中用virtual修饰的函数在子类中被重写,函数声明完全相同。

   如:

class parent{
           public: 
               virtual void drink(){ 
                   cout<<"parent drink()"<<endl; 
               } 
        }; 
        class child:public parent{ 
            public: 
              virtual void drink(){ 
                  cout<<"child drink()"<<endl; 
              } 
        };
   使用基类指针指向子类对象调用drink函数,调用的是子类的drink函数;
   输出:
    child drink()

对以上二种情况进行总结:用virtual修饰的函数,被调用时会调用指针指向的子类对象的方法,而未用virtual修
饰的函数会调用指针类型对象的方法。virtual的实际作用是影响通过指针或引用来调用的方法。

3.基类中未用virtual修饰的函数在子类中被重载。

   如:

class parent{

           public: 
               void drink(int i,int j){ 
                   cout<<"parent drink(int)"<<endl; 
               } 
        }; 
        class child:public parent{ 
           public: 
              void drink(char c){ 
                   cout<<"child drink(char)"<<endl; 
              } 
        };
   使用基类指针或引用指向子类对象调用drink函数,此时无法调用子类的void drink(char)函数。因为是父类
   指针!
   使用子类指针或引用指向子类对象调用drink函数,此时无法调用父类的void drink(int,int)函数。


4.基类中用virtual修饰的关键字在子类中被重载。

   如:

class parent{
               public: 
                   virtual void drink(int i,int j){ 
                       cout<<"parent drink(int)"<<endl; 
                   } 
         }; 
         class child:public parent{ 
              public: 
                  virtual void drink(char c){ 
                      cout<<"child drink(char)"<<endl; 
                 } 
        };

  使用基类指针或引用指向子类对象调用drink函数,此时无法调用子类的void drink(char)函数。原因同上。

   使用子类指针或引用指向子类对象调用drink函数,此时无法调用父类的void drink(int,int)函数。

对以上两种情况进行总结:子类继承父类,子类自动拥有父类的一切未被子类重载的所有非private方法,即一旦子
类重载父类方法,不管有没有virtual关键字修饰,父类中所有被子类重载的同名方法都将不会继承给子类。

另外需要指明的一点是,父类的virtual方法只会影响到它与子孙类之间的关系,并不会影响到父类和祖先类之间的关系。

如果想知道更多有关为何会出现以上的这些情况,请学习有关虚函数表的相关概念,和理解内存中的对象模型。