Reputation: 13
I'm still learning basics of c++, but I'm currently working on a project using derived classes and virtual methods. So the situation is: I have a ClassA
class ClassA
{
public:
virtual void action();
};
And there are two derived classes B and 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;
};
I want to pass a pointer to an object of ClassB as a parameter of action() in ClassC, so I can do something like this:
void ClassC::action(ClassB * ptr)
{
cout << "The value is: " << ptr->valueB;
}
However I cannot find a working way to do it. All of the object pointers are stored in a
vector<ClassA *> objects
where
objects[0]=new ClassC();
objects[1]=new ClassB();
if I try something like
objects[0]->action(object[1])
then I need my virtual method in ClassA to have a parameter ClassB *. And then for a program to recognise the type I tried either including entire ClassB.h (bad idea, it creates a "loop" of includes or something) or using a forward declaration class ClassB; (I get an error about invalid use of incomplete type). And so I'm currently stuck. I hope that everything is clear, but I can of course provide more datails if needed.
Upvotes: 1
Views: 150
Reputation: 363
I notice your ClassC virtual function is declared as taking no parameters:
virtual void action();
but you define your derived class function with a parameter.
void ClassC::action(ClassB * ptr)
The declaration and definition must match. Change the declaration to:
virtual void action(ClassB *);
Hmm. But then you must either include ClassB before the ClassC declaration...
#include "ClassB.h"
or forward declare ClassB. This is a promise to the compiler to properly declare and define the class later. A good place to insert this line would be just before the ClassC declaration.
class ClassB;
Upvotes: 1
Reputation: 1967
You could define action
(in all classes) as:
virtual void action(ClassA * ptr); // or ClassB *
Then you can pass any instance of ClassA or derived from ClassA.
All derived classes can include ClassA with #include "ClassA.h"
, if you provide the Sentinel in the header-File as it is common in c++ :
#ifndef ClassAH
#define ClassAH
...
#endif
So, the header will be included only once...
Upvotes: 0
Reputation: 133669
When you need to forward declare something it is because you can't include the whole definition of the class. In this situation if you forward declare ClassB
the compiler doesn't know about its member attribute valueB
, that's why you get an incomplete type error. To solve this problem you have to factor code something like:
//ClassA.h
class ClassB;
class ClassA
{
virtual void action(ClassB* ptr);
}
//ClassA.cpp
#include "ClassB.h"
void ClassA::action(ClassB* ptr) { ... }
So you are basically using the header to declare the virtual method and forward declare ClassB
, but you define it in ClassA.cpp
, so that in the source file you can include ClassB.h
with no problems and no risks of circular dependencies.
Upvotes: 2