类的C++函数重载

C++ function overload for classes

本文关键字:重载 函数 C++ 类的      更新时间:2023-10-16

我有三个类

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。在编译时不知道它的类型的情况下,如何确保为继承树中最深的对象调用正确的函数?

附言:我相信这是一个棘手的问题,就我的一生而言,我在这里找不到任何结果,因为每个人都在忙于理解"虚拟"关键词,我很清楚,但这不是这里的问题。

因为解析函数重载是在编译时完成的。当您调用函数时,它只看到指针的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、B在它们各自的类中实现虚拟函数:

class A { 
//...
   public:
     virtual void doTask(); 
};
class B : public A {
//...
   public:
     void doTask(); 
};

Ket A::doTask()和B::doTasks()以特定于对象的方式执行各自的任务,即A::doTask()执行将对象的可见性设置为A对象的任务,B::doTask()执行对象的可见性设为B对象的任务。现在,让通话如下:

B* ptr = new B();
A* ptrToB = ptr;
c.method(ptrToB); // pointer is passed

在C::方法(A*ptr)中,它可能类似于:

void C::method(A * ptr) {
  ptr->doTask(); this would actuall call A::doTask() or B::doTask() as dynamically binded
}

感谢@texabruce,我找到了答案,RTTI

代码将如下所示:

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->方法中进行动态转换,所以只有一个

C: :方法(A*ptrOfBase)

然后在C的一个"方法"内做适当的事情(取入或取出C的相应容器成员变量)。

编译器不够聪明,无法猜测要调用哪个方法。在与您的情况相同的情况下,您可能实际上想要调用第一个版本,因为您使用的是A*。这就留给程序员去做:具体一点。如果你不想使用ptr(根据你的意愿调用第二个版本),你需要特别抛出它:

c.method(*((B*)ptrToB));

或更好地使用动态投射:

c.method(*dynamic_cast<B*>(ptrToB));

这可能是不安全的,因为您正在"下转换",在这种情况下,动态转换可能会引发异常,而C样式转换不会,但会导致内存泄漏。你必须非常小心。