I've a question about something what really confuses me!
Let's watch this code righ here:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
class example;
class anything_else;
class A {
public:
A();
};
...
What does class example; and class anything_else; mean,
while class A {}; gets declared? Inside the CPP File i saw definitions like void example::release() { ... } and so on...
I'm really confused, does anyone have a example with class example; ... ?
What does class example; and class anything_else; mean
They are declarations of the classes example and anything_else. They tell the compiler that those are valid class names. This kind of declaration is informally referred to as "forward declaration".
while class A {}; gets declared?
class A gets defined.
Inside the CPP File i saw definitions like void example::release() { ... } and so on...
That's the definition of the function example::release.
Somewhere in the definition of example, there's the declaration of the function:
class example
{
// ...
void release(); // declaration
};
If example is only declared and not defined, then the definition of example::release results in a compilation error.
if you want to have member variables of a type that have not yet been included you do a forward declaration of the type.
class X;
forward declares the class X so you can have a. e.g. a pointer to that class in our class declaration.
class Y
{
...
X* p;
};
later you must supply the definition of the class somewhere in your .cpp file.
Related
I have a problem in C++ that involves circular dependencies and inheritance.
I have implemented the design in parts and I will use pesudocode to ilustrate where the problem happens.
The first part is:
//app.h
include rel.h
class Rel; // forward declaration
class App {
shared_ptr<Rel> //member variable
}
//rel.h
include app.h
class App; //forward declaration
class Rel {
shared_ptr<App> //member variable
}
Until here, the program compiles without warnings
Then, I want to add inheritance as follows:
//app.h
include rel.h
include drel.h
class Rel; // forward declaration
class DRel // forward declaration
class App {
shared_ptr<Rel> //member variable
shared_ptr<DRel> //member variable
}
//rel.h (the same as before)
include app.h
class App; //forward declaration
class Rel {
shared_ptr<App> //member variable
}
//drel.h
include app.h
include rel.h
class App; //forward declaration
class DRel: Rel { // compile error here: expected class name before { token
shared_ptr<App> //member variable
}
As you see, the compiler throws "expected class name before { token" which means that Rel is not resolved, but why the first code without inheritance works and the second one doesn't? How can I fix that? Is that a "wrong" pattern?
I am using c++14
I know there are a lot of questions regarding the issues I am having, but I can't find the answer to my specific problem. Maybe I don't see it...
Since all the variables you declare do not need to know the space occupied by App, Rel and DRel, you don't even need to #include the headers in question, you just have to forward declare the name as you do.
So you have you .h with
class A;
class B;
class C {
std::shared_ptr<A> ptra;
std::shared_ptr<B> ptrb;
};
And then your .cpp with
#include "A"
#include "B"
C::C() { ... }
The original headers files needed to be guarded by #ifdefs like this:
#ifndef CYCLIC_DEPENDECY_1
#define CYCLIC_DEPENDECY_1
#include "cyclic_dependency2.h"
class Rel; // forward declaration
class App {
std::shared_ptr<Rel> test; //member variable
};
#endif
#ifndef CYCLIC_DEPENDECY_2
#define CYCLIC_DEPENDECY_2
#include "cyclic_dependency1.h"
class App; //forward declaration
class Rel {
std::shared_ptr<App> test;//member variable
};
#endif
#include <iostream>
#include <memory>
#include "cyclic_dependency2.h"
class Rel; // forward declaration
class DRel; // forward declaration
class DRel: Rel {
std::shared_ptr<App> test ;//member variable
};
main()
{
}
I've got a class:
class SOMECLASS
{
public:
(...)
static SOMESTRUCT GetInfo();
};
And a struct:
struct SOMESTRUCT
{
(...)
SOMECLASS Instance;
};
They are declared in SOMESTRUCT.h and SOMECLASS.h
I'm not able to compile it, even with forward declarations.
I'm still getting:
error: field ‘Instance’ has incomplete type
How can I solve that?
Try the following
SOMECLASS.h
#ifndef SOMECLASS_H
#DEFINE SOMECLASS_H
class SOMECLASS
{
public:
(...)
static struct SOMESTRUCT GetInfo();
};
#endif // SOMECLASS_H
SOMESTRUCT,h
#ifndef SOMESTRUCT_H
#DEFINE SOMESTRUCT_H
#include "SOMECLASS.h"
struct SOMESTRUCT
{
(...)
SOMECLASS Instance;
};
#endif // SOMESTRUCT_H
The answers given above would have been correct if the users include SOMESTRUCT.h.
If the user do this
#include "SOMECLASS.h"
int main()
{
SOMECLASS::GetInfo();
}
The same error would occur.
The reason is the compiler has to know the full definition of the return variable; otherwise it cannot know how to construct it when the function returns.
When SOMECLASS.h is included, the compiler only knows the identifier SOMESTRUCT is a sturct. If the user calls SOMECLASS::GetInfo, the function has to construct a SOMESTRUCT, so the full definition of the struct has to be given before that line in the same file.
To solve it, it is more reasonable to include SOMESTRUCT.h in SOMECLASS.h, so the user can be sure that calling any function in the class would not result in compilation error, as long as they include the header.
One should also forward declare class SOMECLASS in SOMESTRUCT.h.
If there are cases that only SOMESTRUCT.h is used, then the SOMECLASS.h should also be included in SOMESTRUCT.h, because constructing SOMESTRUCT requires the definition of SOMECLASS.h.
You could avoid this is by declaring Instance variable as SOMECLASS& or SOMECLASS* instead of SOMECLASS.
If you really don't want to expose the detailed definition of the SOMESTRUCT, you can try these
define an IInfo interface class with virtual accessor to get information from SOMESTRUCT
use pimpl idiom
By these ways you don't have to include SOMESTRUCT.h in SOMECLASS.h.
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.
Here is basically what my class layout is:
GameDriver.h:
#ifndef GAMEDRIVER_H
#define GAMEDRIVER_H
#include "CameraSystem.h"
class CameraSystem; //Forward declaration
class GameDriver {
//Stuff
};
#endif
CameraSystem.h:
#ifndef CAMERASYSTEM_H
#define CAMERASYSTEM_H
#include "Tickable.h"
class GameDriver;
class CameraSystem: public Tickable { //Complains here
//Stuff
};
#endif
Tickable.h:
#ifndef TICKABLE_H
#define TICKABLE_H
#include "GameDriver.h"
class GameDriver;
class Tickable {
//Stuff
};
#endif
Here is the error I get:
CameraSystem.h:9 error: expected class-name before '{' token
Forward declaring Tickable does not work either. Any help? Thanks in advance.
If you forward delcare a class you shouldn't include the class' header.
#include "CameraSystem.h" // DO NOT INCLUDE THIS
class CameraSystem; //Forward declaration
class GameDriver {
//Stuff
};
Ok, I see two problems here.
First: Your forward declarations are useless. You are writing (using GameDriver.h: as an example):
#include "CameraSystem.h"
class CameraSystem; //Forward declaration
class GameDriver {
//Stuff
};
Here CameraSystem will already be known by including CameraSystem.h, so the forward declaration is nonsense. What you meant to write was:
class CameraSystem; //Forward declaration
class GameDriver {
//Stuff
};
Second: Where you really would need a forward declaration you cannot use it, as you cannot derive from a forward declared class:
#include "Tickable.h"
class CameraSystem: public Tickable { //Complains here
//Stuff
};
Note that a forward declaration works only if you are not using the forward declared class directly as a class member. You are then restricted to pointers or references to the forward declared class. The reason for this is, that the compiler does not know the memory layout of the class unless its completely known (i.e. by including the header file). For example:
class CameraSystem;
class GameDriver {
CameraSystem m_cameraSystem;
};
will NOT work. However,
class CameraSystem;
class GameDriver {
CameraSystem *m_cameraSystem;
CameraSystem& m_otherCameraSystem;
};
will. Of course you will still have to include the correct header files in your *.cpp file.
You can't resolve such circular dependencies. However, you've got the solution (partially):
I.e. instead of including a header, just use a forward declaration. If you do this right, there shouldn't be any issues. However, try to group your program into logical elements/groups and only add cross-references if they're requied (e.g. the game has to know about and access the camera, but the camera shouldn't have to access the game system as a whole).
You can't inherit from a class that has not been declared.
Pre-processing Tickable.h gives you:
class GameDriver;
class CameraSystem: public Tickable { //Complains here
//Stuff
};
class CameraSystem; //Forward declaration
class GameDriver {
//Stuff
};
class GameDriver;
class Tickable {
//Stuff
};
See how Tickable hasn't even been forward declared when you inherit from it?
Try adding #pragma once at the very beginning of each header file.
You should somehow tell the compiler to only put those once. That's one way. Another is using #ifndef X and #define X.
If this doesn't solve it, try to just eliminate the circular dependency - it doesn't seem like it has to happen...
I'll write an header file,and it's very long.Since it will be too complicated,i don't want to put inner class definition in root class.I mean how can i make a class inner without writing it in root class.
class outer
{
}
class inner
{
}
If i can use like that, The header file will be clearer i think.
Like this:
// foo.hpp
class Foo
{
public:
class Inner;
Foo();
void bar();
Inner zoo();
};
// foo_inner.hpp
#include "foo.hpp"
class Foo::Inner
{
void func();
};
Then, in the implementation:
#include "foo.hpp"
#include "foo_inner.hpp"
void Foo::bar() { /* ... */ }
void Foo::Inner::func() { /* ... */ }
Note that you can use the incomplete type Foo::Inner inside the class definition of Foo (i.e. in foo.hpp) subject to the usual restrictions for incomplete types, e.g. Inner may appear as a function return type, function argument, reference, or pointer. As long as the member function implementations for the class Foo can see the class definition of Foo::Inner (by including foo_inner.hpp), all is well.
You can specify 'outer' as "public class outer", and put both its definition and the "inner" definition into a "class.java" file, and code in outer can instantiate inner just as if inner was in a different source file. It is not clear that is what you're after, because you have not explained why you want an "inner" class.