重载功能(虚拟/非虚拟)

时间:2014-04-01 17:33:10

标签: c++

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

我试图在这里测试一些概念:

  1. 使用虚拟功能重载
  2. 当派生类已实现其自身版本的重载函数时,重载函数将隐藏在派生类中。
  3. 基类指针存储派生类对象时的行为
  4. 派生类中的重载函数,如void vfoo(char x)
  5. #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;
    }
    

3 个答案:

答案 0 :(得分:0)

第一个问题:

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 overriden,则必须将其强制转换为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;

答案 1 :(得分:0)

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

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

Base中的重载分辨率达到最接近的匹配(char - &gt; int)并使用虚拟调度进行调用

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

将ovrload解析和虚拟调度中的匹配与派生匹配。

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

超载分辨率的精确匹配,虚拟调度到基础。

永远不要尝试删除派生类中的功能。

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

答案 2 :(得分:0)

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

在编译时可以很容易地确定常量文字的类型10int2.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);
}

输出:

  


  喵
  哎哟
  MEEEEEOW!
  喵喵