重载函数(虚拟/非虚拟)

Overloaded functions(virtual/non virtual)

本文关键字:虚拟 重载 函数      更新时间:2023-10-16

我有 4 个重载函数vfoo(3 个是虚拟的)

我试图在这里测试几个概念:

  1. 使用虚函数重载
  2. 当派生类实现了自己的重载函数
  3. 版本时,重载函数隐藏在派生类中。
  4. 基类指针存储派生类对象时的行为是什么
  5. 派生类中的重载函数,如 void vfoo( char x )
#include<iostream>
using namespace std;
/*Base class having 4 overloaded function*/  
class ClassBaseV 
{
    public:
        virtual void vfoo( int x ) {
                cout << "ClassBaseV vfoo(int), x = " << x << endl;
        }
        virtual void vfoo( double x ) {
                cout << "ClassBaseV vfoo(double), x = " << x << endl;
        }
        virtual void vfoo( int x, double y ) {
                cout << "ClassBaseV vfoo(int,double), x = " << x << ", y = " << y << endl;
        }
        void vfoo( double x, int y ) {
                cout << "ClassBaseV vfoo(double,int), x = " << x << ", y = " << y << endl;
        }
};

class ClassDerived1 : public ClassBaseV 
{
    public:
        //Overloaded with char x
        void vfoo( char x ) {
                cout << "ClassDerived1 vfoo(char), x = " << x << endl;
        }

         //over riding int x
         void vfoo( int x ) {
                cout << "ClassDerived1 vfoo(int), x = " << x << endl;
        }

};

int main()
{
    ClassBaseV *cB = new ClassDerived1(); /*Base pointer storing derived class object*/
    ClassDerived1 *cd1 = new ClassDerived1(); //Derived class object  
    cd1->vfoo('a');//Direct call using derived class object. this works
    char a = 'a';
    cB->vfoo(a);   // trying to call char x using cB. This calls derived class int How?
    cB->vfoo(10);  // trying to call int x using CB. This calls derived class int 
    cB->vfoo(2.2); // Wanted this to not to work as base class overloaded functions are hidden but this works
    return 1;
}

如果重写派生类中重载集的一部分,通常的做法是使用 using 声明将所有未重写的函数放入作用域。防止令人尴尬的故障。

cB->vfoo(a);   // trying to call char x using cB. This calls derived class int How?

Base 中的过载分辨率获得最接近的匹配项(字符 -> int)并使用虚拟调度进行调用

cB->vfoo(10);  // trying to call int x using CB. This calls derived class int 

派生的过载分辨率和虚拟调度完全匹配。

cB->vfoo(2.2); // Wanted this to not to work as base class overloaded functions are hidden but

过载分辨率精确匹配,虚拟调度到基地。

切勿尝试删除派生类中的功能。

接口继承意味着:我最多需要基础需要的保证,我的行为符合基础合约。

"基类指针存储派生类对象时的行为是什么" - 这是多态性的核心思想。多态性基于基于在运行时确定的对象类型的特定行为,而重载函数在编译时解析。

常量文字的类型可以很容易地在编译时确定,10 int2.2double,这将决定将使用哪个成员函数。然后,实例的类型将确定将使用哪个实现(哪个类)。下面是更简单的示例:

class Animal {
public:
    virtual void makeSound(){ std::cout << "hi" << std::endl; }
    virtual void makeSound(int pain){ std::cout << "ouch" << std::endl; }
    virtual void makeSound(double d){ std::cout << "aaaaaaaargh" << std::endl; }
};
class Cat : public Animal {
public:
    virtual void makeSound(){ std::cout << "meow" << std::endl; }
    virtual void makeSound(int pain){ std::cout << "MEEEEEOW!!!" << std::endl; }
    virtual void makeSound(double d){ std::cout << "meow double" << std::endl; }
};
int main() {
    Animal *a = new Animal();
    Animal *cat = new Cat();
    a->makeSound();
    cat->makeSound();
    a->makeSound(100);
    cat->makeSound(100);
    cat->makeSound(750.80);
}

输出:

你好
猫叫声
哎哟
哎呀呀!!呀��
喵喵双

第一个问题:

cB->vfoo(a);

当你在这里调用vfoo时,它试图在ClassBaseV中找到vfoo(char x)的定义,但它没有,但仍然找到一个可以隐式转换为的vfoo(int x)的定义,所以它从ClassBaseV调用此方法。

编译器将尝试获取作为类型提供的类的方法定义。

ClassBaseV *cB = new ClassDerived1();

在此行中,键入 cB 作为指向 ClassBaseV 的指针。从现在开始,编译器不能查找方法定义(在子类中),但仍然可以查找方法定义,因为 ClassBaseV 知道对父类的任何可能的继承。

第二个问题:

cB->vfoo(2.2);

在这一行中,你调用方法vfoo(double x),因为在ClassBaseV中可以转换为double,并且你不会在ClassDerived1中覆盖此方法。

因此,调用此方法的 ClassBaseV 实现是一种正常行为。

如果你想调用 ClassDerived1 中覆盖的 vfoo 之一,你必须将其转换为 int 或 char(以及松散的信息)

cB->vfoo(static_cast<int>(2.2));

或者在 ClassDerived1 中添加一个新方法,覆盖 ClassBaseV 中的 vfoo(double x)。

另外,如果你想强制 ClassDerived1 从 ClassBaseV 实现方法 vfoo(double x),你必须将其声明为纯虚拟:

virtual void vfoo( double x ) = 0;