I have 2 classes: A and B. Some methods of class A need to use class B and the opposite(class B has methods that need to use class A).
So I have:
class A;
class B {
method1(A a) {
}
}
class A {
method1(B b) {
}
void foo() {
}
}
and everything works fine.
But when I try to call foo() of class A from B::method1 like this:
class B {
method1(A a) {
a.foo();
}
}
I get as result compile errors of forward declaration and use of incomplete type.
But why is this happening? (I have declared class A before using it?)
The compiler hasn't seen the definition of A at the point where you call A::foo(). You can't call a method for an incomplete type - i.e. a type for which the compiler doesn't yet know the definition of. You need to define the calling method after the compiler can see the definition of class A.
class A;
class B
{
public:
void method1(A a);
};
class A
{
public:
void method1(B b) { }
void foo() { }
};
void B::method1(A a)
{
a.foo();
}
In practice, you may want to place the definition for B::method1() in a separate cpp file, which has an #include for the header file containing class A.
C++ INCLUDE Rule : Use forward declaration when possible.
B only uses references or pointers to A. Use forward declaration then : you don't need to include . This will in turn speed a little bit the compilation.
B derives from A or B explicitely (or implicitely) uses objects of class A. You then need to include
Source: http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
For avoiding multiple inclusion of header files you should include a guard, to prevent the compiler from reading the definitions more that once:
#ifndef EMCQUEUE_HH
#define EMCQUEUE_HH
// rest of header file ...
// definition code here...
#endif
See Industrial Strength C++ Chapter Two: Organizing the code.
Related
In a single header file, I have 2 class declaration. And one of them contains const value that I would like to use on top declared class.
Following is the basic implementation.
class B;
class A
{
public :
friend class B; // this should not matter since CONST_VAL is public
int a;
A() { a = B::CONST_VAL; } // !!! error line
}
class B
{
public :
static const int CONST_VAL = 1;
}
I feel this should be very basic concept, but I am getting compiler error. error C2027 : use of undefined type 'B' as well as error 2065: 'CONST_VAL': undeclared identifier
Why would this constructor think it does not know B nor B::CONST_VAL?
In the code you've given, B is forward declared at the top of the file:
class B;
...
This tells the compiler that B exists as a class, but the compiler doesn't know anything about B because its definition hasn't yet appeared. With a forward declaration like this, it doesn't make sense to use any B objects or members. You're allowed to use B* pointers because they don't require any implementation details of B however.
To fix this, you need to provide the definition of B before it's needed, either at the top of the file, or in a separate header file that you #include. For example:
class B {
public :
static const int CONST_VAL = 1;
};
class A {
public :
int a;
A() : a(B::CONST_VAL) { }
}
I'm trying to build a solution which has three files. With main.cpp it is four files.
Entity.h
#pragma once
#include "SystemBase.h"
namespace Engine {
class Entity {
public:
Entity() { }
void s(SystemBase* sb) { }
};
}
SubscribersList.h
#pragma once
#include "SystemBase.h"
#include "Entity.h"
namespace Engine {
class SubscribersList {
friend SystemBase;
public:
SubscribersList() { }
void f(Entity* e) { }
};
}
SystemBase.h
#pragma once
#include "SubscribersList.h"
#include "Entity.h"
namespace Engine {
class SystemBase {
public:
SystemBase() { }
void g(Entity* e) { }
private:
SubscribersList m;
};
}
Don't focus on the body's of methods in the headers. It is just to keep things simple. I found two ways to build the solution.
1. Write the word class before all class names. But it crashes when I try to separate the realization from prototypes.
2. Write all code in one file.
I don't/won't write the keyword class before all class names to build the solution, and certainly I don't/won't write a big project in one file. So why I can't build it? What is the magic?!
To understand the problem of cyclic header dependency we first need understand the difference between a class declaration and definition and the concept of incomplete types.
A prototype or forward declaration of a type Type is written as:
class Type;
Such a forward declaration allows you to create pointers and reference to that type.
You cannot however instantiate, dereference pointers to or use a reference to Type until its full type is declared.
A declaration for Type could be written as:
class AnotherType;
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now we have the declaration instances can be created and pointers to Type can be dereferenced.
However before m_theOtherThing is dereferenced or instanciated AnotherType must be fully declared.
class AnotherType {
Type m_aType;
}
Should do, which gives us both the full declaration and definition of AnotherType.
That allows to continue on to write the definition of Type::aMemberFunc:
void Type::aMemberFunc() {
m_theOtherThing = new AnotherType();
}
If instead of presenting this code to the compiler in this order we instead presented the full declarations of Type and AnotherType up front:
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
class AnotherType {
Type m_aType;
}
Then AnotherType *m_theOtherThing; will fail to compile as AnotherType has not been declared or forward declared by that point.
Switching the order gives:
class AnotherType {
Type m_aType;
}
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now Type m_aType; will not compile as Type has not been declared. A forward declaration would not do in this case.
Using #pragma once instead of header guards does not in anyway change the problem. #pragma once only ensures the header is include just once it does not effect the order the compiler processes the code otherwise. It certainly does not allow the compiler to ignore undefined types when it reaches them.
For this kind of class structure there is no way for the compiler to be able to process it without the use for forward declarations.
Im trying to do a C++ class function that can return other classes values. The code works if class A is defined first but i have more code that i dont want to mangle around. I figured i need somekind of forward declaration for class A.
What kind of forward declaration do i need to get this work? All my code is in one file. Does this problem dissapear if i properly split my classes to multiple files and include them to project or does it make any difference to VC++ compiler?
Semi pseudo code below.
// forward declaration
class A;
// class deifinitions
class B {
private:
int testvalue;
public:
void settestvalue(A &Aobj);
}
void B::settestvalue(A &Aobj) {
testvalue = Aobj.settestvalue();
}
class A {
private:
int test = 10;
public:
int testvalue();
};
int A::testvalue() {
return test;
}
// mainloop
A Aobj;
B Bobj;
Bobj.settestvalue (Aobj);
just put the defination of B's member-function after A's class definition.
I'm creating a static library in C++ to define a class that others can use in their code. However, a member of the class is of a type defined in a header file obtained from someone else, and I don't want to distribute the contents of this person's header file.
Here is the current public interface (interface.h):
class B {
TypeToHide t;
// other stuff ...
};
class A {
double foo();
B b;
};
And here is the code that will be compiled into a static library (code.cpp):
double A::foo() {
// ...
}
And here is the file whose contents I need to hide from public view (HideMe.h):
struct TypeToHide {
// stuff to hide
};
What can I do hide the contents of HideMe.h? Ideally, I could just stick the entire struct from HideMe.h into code.cpp.
You can use the PIMPL idiom (Chesshire Cat, Opaque Pointer, whatever you want to call it).
As the code is now, you can't hide the definition of TypeToHide. The alternative is this:
//publicHeader.h
class BImpl; //forward declaration of BImpl - definition not required
class B {
BImpl* pImpl; //ergo the name
//wrappers for BImpl methods
};
//privateHeader.h
class BImpl
{
TypeToHide t; //safe here, header is private
//all your actual logic is here
};
Simpler than Pimpl, you can use a pointer to TypeToHide and a forward declaration for it:
class B {
TypeToHide* t;
// other stuff ...
};
As long as you won't need knowledge about t's internal structure for the user's code, you won't have to expose it and it will stay safe in your library.
The code inside the library will have to know what TypeToHide is, but that's not a problem.
I have a base interface class:
class A
{
public:
ITask(){}
virtual bool Start()=0;
virtual void Update()=0;
virtual void Stop()=0;
};
I now have 2 other classes, that inherit from this
#include "A.h"
#include "C.h"
class B: public A
{
public:
bool Start(){}
void Update()
{
c.Start();
}
void Stop(){}
static bool m_run;
static void SetRun(bool run)
{
m_run = run;
}
private:
C c;
};
lastly I have a 3rd class:
#include "A.h"
#include "B.h"
class C : public A
{
public:
bool Start()
{
B::SetRun(false); // cant do this
B::m_run = false; // or this
}
void Update()
{
}
void Stop()
{
}
}
I have shaved down some of the code, for simplicity.
I dont understand why I cant access the static var in B. Do I need to make it a pointer or a ref?
I get 2 errors:
error C2653: 'B' : is not a class or namespace name
error C3861: 'm_run': identifier not found
Although you don't show it, I'm assuming that B.h includes C.h; otherwise the line C c; won't compile. This causes a circular dependency in the header files: B.h must be included before C.h, which must be included before B.h, which is impossible.
The easiest solution is to move the body of C::Start out of the definition of C, so that C.h does not need to include B.h. The function definition can go into a source file, or a separate header if you want to keep it inline.
Alternatively, you could modify B to contain a std::unique_ptr<C> rather than an instance of C, and implement a constructor (in a source file, or a separate header) that initialises it with new C. Then B.h only needs to forward declare class C; rather than including C.h.
A better solution, if possible, would be to rethink the relationships between the classes so that there isn't a circular dependency.
(UPDATE: while I was writing this answer, the question changed to show that B.h does indeed include C.h as I guessed.)
There is nothing wrong with your example code (after the edits), the problem must be somewhere else, like a failed include.