我有4个重载函数vfoo
(3个是虚拟的)
我试图在这里测试一些概念:
#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;
}
答案 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)
“基类指针存储派生类对象时的行为是什么” - 这是多态的核心思想。 多态性基于运行时中确定的对象类型的特定行为,而重载函数在编译时中解析。
在编译时可以很容易地确定常量文字的类型10
是int
,2.2
是double
,这将决定将使用哪个成员函数。然后,实例的类型将确定将使用哪个实现(哪个类)。这是一个更简单的例子:
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!
喵喵