C++ C++;基于派生类的重载方法
我的代码面临以下问题:C++ C++;基于派生类的重载方法,c++,overloading,derived-class,C++,Overloading,Derived Class,我的代码面临以下问题: #include <iostream> using namespace std; class Base { public: virtual void sayHello()=0; }; class Impl1 : public Base { public: void sayHello() { cout << "Hi from Impl1" << endl; } }; class Impl2 : public Bas
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
#包括
使用名称空间std;
阶级基础{
公众:
虚拟void sayHello()=0;
};
第1类:公共基础{
公众:
void sayHello(){cout重载解析在编译时执行。这意味着forsayHello(b);
,编译器只知道b
的类型是Base*
,它不会也不可能知道b
实际上指向Impl1
对象。然后导致调用不明确;将Base*
转换为Impl1*
或Impl2*
是调用的等效秩
PS:可能是OT,但对于您的代码示例,使用Base*
的函数可以正常工作;动态dispach将生效
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
由于重载是在编译时解析的,因此必须向编译器提供确切的类型,才能成功解析重载
要在类型上分派,请将虚拟成员函数添加到基
,并使用它选择重载:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
类基{
公众:
虚拟void sayHello()=0;
虚拟void callSayHello()=0;
};
第1类:公共基础{
公众:
void sayHello(){cout去掉两个独立函数,直接调用b->sayHello();
:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
或者在动态\u cast
中使用难看的解决方法:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
Impl1*i1=newimpl1();
基*b=i1;
sayHello(dynamic_cast(b));;
求助于dynamic_cast
的需要通常表明类设计中存在错误。这里很可能就是这种情况。很有可能你根本就不应该引入所谓的面向对象基类
还要注意的是,您没有在最后调用delete
。如果调用,则需要在Base
中使用虚拟析构函数。您没有将Base*
作为参数的sayHello函数。我基本上希望将我的对象传递给一个函数,该函数根据对象的类型执行一些计算。我的对象是故意的缺少进行所需计算所需的信息。@ZdravkoDonev:我添加了一个替代解决方案。是的,我想到了if
-else if
和dynamic\u cast,但这似乎不是一个好主意。关于引入基类的问题,也许你是对的。但是在我的代码的某些部分,我需要处理我的实现离子作为一个基类,在另一个基类中,我需要区分它们。那么我如何在运行时进行此对话呢?我基本上是想将我的对象传递给一个函数,该函数根据对象的类型进行一些计算。我的对象故意缺少信息,以便进行所需的计算。@ZdravkoDonev所以您需要知道实际情况。@ZdravkoDonevl函数内部的派生类型?您可能需要dynamic_cast
。因此您建议:if(dynamic_cast(b)){}else if(dynamic_cast(b)){}else{//“谁知道”类型}解决方案?@ZdravkoDonev您可以这样做,但这不是一个好主意。我的答案中显示的第一个代码示例会更好;不要依赖于实际的派生类型,而是依赖于接口(即Base
class).是的,但是我的派生类不包含进行计算所需的数据,我不想传递不同类的对象,因为我将得到一个意大利面代码。在这种情况下,我应该怎么做?
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));