2015-12-30 60 views
1

我仍在学习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; 
}; 

我想一个指针传递给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; (我收到关于对不完整类型的无效使用的错误)。所以我现在被卡住了。我希望一切都很清楚,但如果需要的话,我当然可以提供更多的数据。

+0

对。因为将一个'A *'盲目地下传到'B *' –

+0

是不安全的,那么如何摆脱valueB和valueC并且只是一个int值;在ClassA中? – tetorea

+0

您可以在另一个类的头文件中使用类ClassB的前向声明,并在cpp-File中使用include。如前所述,与哨兵一起,它将避免循环... –

回答

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,没有问题,也没有循环依赖的风险。

+0

我刚测试过这个解决方案,它工作得很好。唯一的区别是我将ClassB.h包含在ClassC.cpp中而不是ClassA.cpp中。您的解决方案导致相同的错误(不完整类型)。我不知道为什么,但可能是因为ClassC.h包含ClassA.h(前向声明的位置),但对ClassA.cpp没有任何了解(实际定义在哪里)? – nabacc001

0

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

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

然后你就可以通过ClassA的任何实例或从ClassA的派生。 所有派生类可以包括ClassA的与#include "ClassA.h",如果你在报头文件提供的哨兵,因为它是在C++常见:

#ifndef ClassAH 
#define ClassAH 

... 

#endif 

因此,头将被纳入只有一次......

+0

不确定,但我认为OP请求了一个'ClassB *'类型的参数。 –

+0

也可以...我编辑它... –

+0

你在它们之间编辑它。没有前向声明,'ClassB *'不能在参数列表中使用。 –

1

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

virtual void action(); 

但是您可以使用参数定义派生类函数。

void ClassC::action(ClassB * ptr) 

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

virtual void action(ClassB *); 

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

#include "ClassB.h" 

或正向声明ClassB。这是编译器在稍后正确声明和定义类的承诺。插入这一行的好地方就在ClassC声明之前。

class ClassB; 
+1

答案并不错。但是,读者应该如何知道在哪里插入前向声明?请注意,OP仍然学习C++的基础知识。 –

+0

编辑建议放置前置声明的地方。感谢您的帮助。 :) –