C++中派生类与基类中的虚函数参数不同会产生什么情况

时间:2022-06-01 20:43:10
#include<iostream>
using namespace std;

class A
{
public:
virtual void disp(int n)
{
cout << "A::disp n=" << n << endl;
}
};
class B : public A
{
public:
virtual void disp(double m)
{
cout << "B::disp m=" << m << endl;
}
};
void fun(A &a)
{
a.disp(6.5);
}
void main()
{
B b;
fun(b);
b.disp(6);
b.disp(6.5);
}

这段代码执行的结果是:
A::disp n=6
B::disp m=6
B::disp m=6.5
主要有两个问题:
1.为什么第一条结果不是 B::disp m=6.5  ?
2.为什么第二条结果不是  A::disp  n=6?

存在疑惑:
1.执行fun(b)的时候不是等于执行b.disp(6.5)的吗?
2.由于类B的虚函数参数与类A不同,故类B相当于有两个disp函数是重载的关系

class B
{
virtual void disp(int n)
virtual void disp(double m)
}

这样的话执行b.disp(6)的时候调用virtual void disp(int n)执行结果应该为A::disp n=6
由于是新手,各位大神帮忙分析一下此程序,并指出我的想法的问题,谢谢。

4 个解决方案

#1


你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

#2


引用 1 楼 jianwen0529 的回复:
你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?

#3


引用 2 楼 xin07020227 的回复:
Quote: 引用 1 楼 jianwen0529 的回复:

你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?


因为b绑定为A类型,你A中只有disp

引用 2 楼 xin07020227 的回复:
Quote: 引用 1 楼 jianwen0529 的回复:

你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?


b绑定到 A 类型的引用,显而易见的是调用的disp(int n)这个函数,又因为你派生类是覆盖了这个虚函数而不是重写它,所以并没有引发多态的效果
那么它当然执行的是基类这个函数的代码

你double 类型转为 int 至少会引发一个警告吧?

#4


在C++,如果想搞 多态的话,基类和派生类中的 虚函数的参数必须一模一样(参数个数和参数类型)。

如果基类和派生类的两个函数的函数名一样,但是参数不一样,那就无法override(重写)。同时也不是overload(重载),因为不是在同一个scope(作用域)里面。这样的话,这两个函数就没有半毛钱关系了。

可以看看这个文章:http://developer.51cto.com/art/201106/266705.htm

#1


你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

#2


引用 1 楼 jianwen0529 的回复:
你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?

#3


引用 2 楼 xin07020227 的回复:
Quote: 引用 1 楼 jianwen0529 的回复:

你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?


因为b绑定为A类型,你A中只有disp

引用 2 楼 xin07020227 的回复:
Quote: 引用 1 楼 jianwen0529 的回复:

你派生类声明了一个同名称却不同签名的函数,会覆盖掉基类的同名函数
对派生类对象不可见,你可以用下面代码测试下是否被隐藏

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    // 用int的参数看看是否能调用到基类的那个函数,因为int找不到之后不会去匹配char*的参数,你之前double是可以匹配的,所以编译能通过
    virtual void disp(char *str)
    {
        cout << "B::disp m=" << str << endl;
    }
};


如果派送类令基类被覆盖的函数可见,可以试试下面代码

class A
{
public:
    virtual void disp(int n)
    {
        cout << "A::disp n=" << n << endl;
    }
};
class B : public A
{
public:
    using A::disp;
    virtual void disp(double m)
    {
        cout << "B::disp m=" << m << endl;
    }
};


又或者你测试下

非常感谢,看了您的解释我明白了b.disp(6)执行的结果为什么为B::disp m=6
但是还有点疑问,既然派生类Bvirtual void disp(double m)函数覆盖了基类的virtual void disp(int n),
那当执行fun(b)的时候结果不是应该与b.disp(6.5)的结果一样的吗 ?为什么fun(b)的结果是A::disp n=6
而b.disp(6.5)的结果是B::disp m=6.5?


b绑定到 A 类型的引用,显而易见的是调用的disp(int n)这个函数,又因为你派生类是覆盖了这个虚函数而不是重写它,所以并没有引发多态的效果
那么它当然执行的是基类这个函数的代码

你double 类型转为 int 至少会引发一个警告吧?

#4


在C++,如果想搞 多态的话,基类和派生类中的 虚函数的参数必须一模一样(参数个数和参数类型)。

如果基类和派生类的两个函数的函数名一样,但是参数不一样,那就无法override(重写)。同时也不是overload(重载),因为不是在同一个scope(作用域)里面。这样的话,这两个函数就没有半毛钱关系了。

可以看看这个文章:http://developer.51cto.com/art/201106/266705.htm