C++ C++;类的函数重载
我有三节课C++ C++;类的函数重载,c++,inheritance,overloading,C++,Inheritance,Overloading,我有三节课 class A { //... } class B : public A { //... } C类: #include "A.h" #include "B.h" class C { void method(A anObjOfA); void method(B anObjOfB); } 现在如果我这样做了 B* ptr = new B(); A* ptrToB = ptr; c.method(*ptrToB); 它为类型A的对象调用方法,而不是继承的实际类型B。
class A {
//...
}
class B : public A {
//...
}
C类:
#include "A.h"
#include "B.h"
class C
{
void method(A anObjOfA);
void method(B anObjOfB);
}
现在如果我这样做了
B* ptr = new B();
A* ptrToB = ptr;
c.method(*ptrToB);
它为类型A的对象调用方法,而不是继承的实际类型B。。如何确保调用了继承树中最深对象的正确函数,而不在编译时实际知道它的类型
PS:我敢肯定这是一个noob问题,就我个人而言,我在这里找不到任何结果,因为每个人都在忙于理解“virtual”关键字,这对我来说非常清楚,但不是这里的问题。因为解决函数重载是在编译时完成的。调用函数时,它只看到指针的
A
部分,即使它可能指向B
也许你想要的是:
class A
{
public:
virtual void DoWorkInC()
{
cout << "A's work";
}
virtual ~A() {}
};
class B : public A
{
public:
virtual void DoWorkInC()
{
cout << "B's work";
}
};
class C
{
void method(A& a)
{
a.DoWorkInC();
}
}
A类
{
公众:
虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟公司
{
cout因为解决函数重载是在编译时完成的。调用函数时,它只看到指针的a
部分,即使它可能指向B
也许你想要的是:
class A
{
public:
virtual void DoWorkInC()
{
cout << "A's work";
}
virtual ~A() {}
};
class B : public A
{
public:
virtual void DoWorkInC()
{
cout << "B's work";
}
};
class C
{
void method(A& a)
{
a.DoWorkInC();
}
}
A类
{
公众:
虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟虚拟公司
{
不能让您的类A、B在各自的类B中实现虚拟函数:
class A {
//...
public:
virtual void doTask();
};
class B : public A {
//...
public:
void doTask();
};
Ket A::doTask()和B::doTask()以对象特定的方式执行各自的任务,即A::doTask()以对象集为A对象的可见性执行任务,B::doTask()以对象集为B对象的可见性执行任务。
现在,让电话是这样的:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
在C::method(A*ptr)中,它可能类似于:
void C::method(A * ptr) {
ptr->doTask(); this would actuall call A::doTask() or B::doTask() as dynamically binded
}
让您的类A、B在各自的类B中实现虚拟函数:
class A {
//...
public:
virtual void doTask();
};
class B : public A {
//...
public:
void doTask();
};
Ket A::doTask()和B::doTask()以对象特定的方式执行各自的任务,即A::doTask()以对象集为A对象的可见性执行任务,B::doTask()以对象集为B对象的可见性执行任务。
现在,让电话是这样的:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
在C::method(A*ptr)中,它可能类似于:
void C::method(A * ptr) {
ptr->doTask(); this would actuall call A::doTask() or B::doTask() as dynamically binded
}
编译器不够聪明,无法猜出要调用哪个方法。在与您相同的情况下,您可能实际上想要调用第一个版本,因为您使用的是a*
。这让程序员需要处理:具体一点。如果您不想使用ptr
(按照您的意愿调用第二个版本),您需要专门对其进行强制转换:
c.method(*((B*)ptrToB));
或者更好地使用动态强制转换:
c.method(*dynamic_cast<B*>(ptrToB));
c.method(*dynamic_cast(ptrToB));
这可能是不安全的,因为您正在“向下投射”在这种情况下,动态强制转换可能会引发异常,而C样式强制转换不会引发异常,但会导致内存泄漏。您必须非常小心。编译器不够聪明,无法猜测您要调用哪个方法。在与您的情况相同的情况下,您可能实际上需要调用第一个版本,因为您使用的是a*
。这就让程序无法运行要处理的mer:要具体。如果您不想使用ptr
(如您所愿调用第二个版本),则需要专门强制转换它:
c.method(*((B*)ptrToB));
或者更好地使用动态强制转换:
c.method(*dynamic_cast<B*>(ptrToB));
c.method(*dynamic_cast(ptrToB));
这可能是不安全的,因为您正在“向下转换”,在这种情况下,动态转换可能会引发异常,而C样式转换不会,但会导致内存泄漏。您必须非常小心。感谢@texasbruce,我找到了答案
代码如下所示:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
A*someAOrBPtr=。。。
...
B*testBPtr=动态(someAOrBPtr);
if(testBPtr){
//我们的怀疑得到了证实——这确实是一个B
C->方法(testBPtr);
}否则{
//我们的怀疑是不正确的——它绝对不是B。
//someAOrBPtr指向基A的某个其他子类的实例。
C->方法(someAOrBPtr);
};
编辑:事实上,我可能会在C->方法中进行动态转换,所以只有一个
C::方法(A*ptrOfBase)
然后在C的一个“方法”中做适当的事情(输入或输出C的相应容器成员变量)。感谢@texasbruce,我找到了答案
代码如下所示:
B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed
A* someAOrBPtr = ...
...
B* testBPtr = dynamic_cast<B*>(someAOrBPtr);
if( testBPtr ){
// our suspicions are confirmed -- it really was a B
C->method(testBPtr);
}else{
// our suspicions were incorrect -- it is definitely not a B.
// The someAOrBPtr points to an instance of some other child class of the base A.
C->method(someAOrBPtr);
};
A*someAOrBPtr=。。。
...
B*testBPtr=动态(someAOrBPtr);
if(testBPtr){
//我们的怀疑得到了证实——这确实是一个B
C->方法(testBPtr);
}否则{
//我们的怀疑是不正确的——它绝对不是B。
//someAOrBPtr指向基A的某个其他子类的实例。
C->方法(someAOrBPtr);
};
编辑:事实上,我可能会在C->方法中进行动态转换,所以只有一个
C::方法(A*ptrOfBase)
然后执行适当的操作(输入或输出相应的容器成员变量C)在C++中的一个“方法”中,你是不是提供了<代码>虚拟<代码> >方法>代码>类A<代码>,还是纯<代码>虚拟< /代码>接口?为什么你认为<>代码>虚拟< /代码>在这里不是问题?你所寻找的是被调用的,它不包含在C++中。但是,你可以重新构建你的类,使<代码>方法>/code>是a
上的一个虚拟方法,在B
中有一个不同的实现,完全摆脱了C
。然后(通过C++的单个动态调度),在实例上调用方法将确保调用正确的版本。@πάνταῥεῖ: 都不是。请看问题。@Cameron我已经发表了这篇评论,甚至在问题的PS:part编写之前。无论如何,OP不清楚这一点,为什么不应该使用virtual
。实际上,C是一个非常大的类,它处理许多其他类的管理,其中包括一个基类a和一些与之相关的类t来自A的一些方法和属性(称它们为B1…B8),但由于这些类在功能上与它们的祖先共享的方法非常不同,因此在调用上述“方法”时,我需要对它们进行非常不同的处理。您的意思是为类A
提供虚拟方法吗