将一个指向一个派生类的指针传递给另一个

Passing a pointer to one derived class to another

本文关键字:一个 另一个 指针 派生      更新时间:2023-10-16

我仍在学习c++的基础知识,但我目前正在使用派生类和虚拟方法进行一个项目。因此,情况是:我有一个a级

class ClassA
{
public:
    virtual void action();
};

有两个派生类B和C:

#include "ClassA.h" 
class ClassB: public ClassA
{
public:
    virtual void action();
    int valueB;
};

-

#include "ClassA.h"
class ClassC: public ClassA
{
public:
    virtual void action();
    int valueC;
};

我想传递一个指向ClassB对象的指针,作为ClassC中action()的参数,这样我就可以做这样的事情:

void ClassC::action(ClassB * ptr)
{
cout << "The value is: " << ptr->valueB;
}

然而,我找不到一种工作方法。所有的对象指针都存储在中

vector<ClassA *> objects

其中

objects[0]=new ClassC();
objects[1]=new ClassB();

如果我尝试之类的东西

objects[0]->action(object[1])

那么我需要我在ClassA中的虚拟方法有一个参数ClassB*。然后,为了让程序识别我尝试过的类型,要么包括整个ClassB.h(坏主意,它创建了一个包含或其他内容的"循环"),要么使用前向声明类ClassB;(我收到一个关于无效使用不完整类型的错误)。所以我现在被卡住了。我希望一切都清楚,但如果需要的话,我当然可以提供更多的数据。

当您需要转发声明某个东西时,这是因为您不能包含类的整个定义。在这种情况下,如果正向声明ClassB,编译器不知道其成员属性valueB,这就是为什么会得到不完整的类型错误。为了解决这个问题,你必须对代码进行因子编码,比如:

//ClassA.h
class ClassB;
class ClassA
{
  virtual void action(ClassB* ptr);
}
//ClassA.cpp
#include "ClassB.h"
void ClassA::action(ClassB* ptr) { ... }

因此,您基本上是使用标头来声明虚拟方法和前向声明ClassB,但您在ClassA.cpp中定义了它,以便在源文件中包含ClassB.h,而不会出现问题,也不会有循环依赖的风险。

我注意到您的ClassC虚拟函数被声明为不带参数:

virtual void action();

但是您用一个参数定义派生类函数。

void ClassC::action(ClassB * ptr)

声明和定义必须匹配。将声明更改为:

virtual void action(ClassB *);

嗯。但是,您必须在ClassC声明之前包含ClassB。。。

#include "ClassB.h"

或转发声明ClassB。这是对编译器的承诺,可以在以后正确地声明和定义类。插入这一行的好地方是在ClassC声明之前。

class ClassB;

您可以将action(在所有类中)定义为:

virtual void action(ClassA * ptr); // or ClassB *

然后,您可以传递ClassA的任何实例或从ClassA派生的实例。如果在头文件中提供Sentinel,则所有派生类都可以包括带有#include "ClassA.h"的ClassA,因为它在c++:中很常见

#ifndef ClassAH
#define ClassAH
...
#endif

因此,标头将只包含一次。。。

相关文章: