我还在学习c ++的基础知识,但我目前正在使用派生类和虚拟方法开展项目。所以情况是: 我有一个ClassA
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;
};
我想在ClassC中传递一个指向ClassB对象的指针作为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(坏主意,它创建一个&#34;循环&#34;包含什么)或使用前向声明类ClassB; (我收到有关无效使用不完整类型的错误)。所以我现在卡住了。我希望一切都很清楚,但如果需要,我当然可以提供更多数据。
答案 0 :(得分:2)
当你需要转发声明的东西时,因为你不能包含整个类的定义。在这种情况下,如果您转发声明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
没有问题,没有循环依赖的风险。
答案 1 :(得分:1)
我注意到你的ClassC虚函数被声明为不带参数:
virtual void action();
但您使用参数定义派生类函数。
void ClassC::action(ClassB * ptr)
声明和定义必须匹配。将声明更改为:
virtual void action(ClassB *);
嗯。但是,你必须在ClassC声明之前包括ClassB ......
#include "ClassB.h"
或转发声明ClassB。这是对编译器的承诺,以便稍后正确声明和定义该类。插入此行的好地方就在ClassC声明之前。
class ClassB;
答案 2 :(得分:0)
您可以将action
(在所有类中)定义为:
virtual void action(ClassA * ptr); // or ClassB *
然后,您可以传递ClassA的任何实例或从ClassA派生。
所有派生类都可以包含带有#include "ClassA.h"
的ClassA,如果你在头文件中提供Sentinel,因为它在c ++中很常见:
#ifndef ClassAH
#define ClassAH
...
#endif
因此,标题只会被包含一次......