C ++ class advanced declaration

When I try to compile this code, I get:

52 C:\Dev-Cpp\Projektyyy\strategy\Tiles.h invalid use of undefined type `struct tile_tree_apple' 46 C:\Dev-Cpp\Projektyyy\strategy\Tiles.h forward declaration of `struct tile_tree_apple' 

part of my code:

 class tile_tree_apple; class tile_tree : public tile { public: tile onDestroy() {return *new tile_grass;}; tile tick() {if (rand()%20==0) return *new tile_tree_apple;}; void onCreate() {health=rand()%5+4; type=TILET_TREE;}; }; class tile_tree_apple : public tile { public: tile onDestroy() {return *new tile_grass;}; tile tick() {if (rand()%20==0) return *new tile_tree;}; void onCreate() {health=rand()%5+4; type=TILET_TREE_APPLE;}; tile onUse() {return *new tile_tree;}; }; 

I really don’t know what to do, I was looking for a solution, but I couldn’t find anything similar to my problem ... Actually, I have more classes with a parent “tile”, and that was fine before ... Thanx for any help.

EDIT:

I decided to change all return types to pointers to avoid memory leaks, but now I got:

 27 C:\Dev-Cpp\Projektyyy\strategy\Tiles.h ISO C++ forbids declaration of `tile' with no type 27 C:\Dev-Cpp\Projektyyy\strategy\Tiles.h expected `;' before "tick" 

It is unique in the base class, everything else is in order ... Each function of the tile class that returns * tile has this error ...

Some codes:

 class tile { public: double health; tile_type type; *tile takeDamage(int ammount) {return this;}; *tile onDestroy() {return this;}; *tile onUse() {return this;}; *tile tick() {return this}; virtual void onCreate() {}; }; 
+8
c ++ class forward-declaration
source share
9 answers

To compile new T , T must be a full type. In your case, when you say new tile_tree_apple inside the definition of tile_tree::tick , tile_tree_apple is incomplete (it was declared ahead, but its definition is later in your file). Try moving the built-in definitions of your functions to a separate source file, or at least move them after the class definitions.

Something like:

 class A { void f1(); void f2(); }; class B { void f3(); void f4(); }; inline void A::f1() {...} inline void A::f2() {...} inline void B::f3() {...} inline void B::f4() {...} 

When you write your code in this way, all references to A and B in these methods are guaranteed to refer to full types, since there are no more links!

+11
source share

Use a forward declaration if necessary.

Suppose you want to define a new class B that uses objects of class A

  • B uses links or pointers to A only. Use forward declaration, then you do not need to include <Ah> . This, in turn, speeds up compilation a bit.

     class A ; class B { private: A* fPtrA ; public: void mymethod(const& A) const ; } ; 
  • B comes from A or B explicitly (or implicitly) uses objects of class A Then you need to enable <Ah>

     #include <Ah> class B : public A { }; class C { private: A fA ; public: void mymethod(A par) ; } 
+15
source share

A forward-looking declaration is an "incomplete type", the only thing you can do with this type is to create a pointer to it or reference it in a function declaration (that is, an argument or return type in a function prototype). On line 52 of your code, you are trying to instantiate an object.

At this moment, the compiler does not know about the size of the object and its constructor, so it cannot create an instance of the object.

+5
source share

I had this:

 class paulzSprite; ... struct spriteFrame { spriteFrame(int, int, paulzSprite*, int, int); paulzSprite* pSprite; //points to the sprite class this struct frames static paulzSprite* pErase; //pointer to blanking sprite int x, y; int Xmin, Xmax, Ymin, Ymax; //limits, leave these to individual child classes, according to bitmap size bool move(int, int); bool DrawAt(int, int); bool dead; }; spriteFrame::spriteFrame(int initx, int inity, paulzSprite* pSpr, int winWidth, int winHeight) { x = initx; y= inity; pSprite = pSpr; Xmin = Ymin = 0; Xmax = winWidth - pSpr->width; Ymax = winHeight - pSpr->height; dead = false; } 

...

It turned out the same grief as in the original question. Just solved by moving the paulzSprite definition to after after on spriteFrame. Shouldn't the compiler be smarter than that (VC ++, VS 11 Beta)?

And by the way, I completely agree with Clifford's remark above, "Pointers do not cause memory leaks, bad coding causes memory leaks." IMHO this applies to many other new features of "smart coding", which should not replace the understanding of what you are actually asking for the computer to do.

+5
source share

The problem is that tick() must know the definition of tile_tree_apple , but all it has is its direct declaration. You should separate declarations and definitions like this:

tile_tree.h

 #ifndef TILE_TREE_H #define TILE_TREE_H #include "tile.h" class tile_tree : public tile { public: tile onDestroy(); tile tick(); void onCreate(); }; #endif 

tile_tree.cpp :

 tile tile_tree::onDestroy() { return *new tile_grass; } tile tile_tree::tick() { if (rand() % 20 == 0) return *new tile_tree_apple; } void tile_tree::onCreate() { health = rand() % 5 + 4; type = TILET_TREE; } 

Except you have a main problem: you allocate memory (using new ), then copy the selected object and return a copy. This is called a memory leak because you have no way to free the memory that it uses. Not only that, but you copy tile_tree to tile , which discards information that distinguishes tile_tree from tile ; this is called slicing.

You want to return a pointer to a new tile , and at some point you call delete to free memory:

 tile* tile_tree::tick() { if (rand() % 20 == 0) return new tile_tree_apple; } 

Even better would be to return a smart pointer that will handle memory management for you:

 #include <memory> std::shared_ptr<tile> tile_tree::tick() { if (rand() % 20 == 0) return std::make_shared<tile_tree_apple>(); } 
+4
source share

the tile_tree_apple class must be defined in a separate .h file.

 tta.h: #include "tile.h" class tile_tree_apple : public tile { public: tile onDestroy() {return *new tile_grass;}; tile tick() {if (rand()%20==0) return *new tile_tree;}; void onCreate() {health=rand()%5+4; type=TILET_TREE_APPLE;}; tile onUse() {return *new tile_tree;}; }; file tt.h #include "tile.h" class tile_tree : public tile { public: tile onDestroy() {return *new tile_grass;}; tile tick() {if (rand()%20==0) return *new tile_tree_apple;}; void onCreate() {health=rand()%5+4; type=TILET_TREE;}; }; 

another: returning a tile, not a link to a tile, is not a good idea if the tile is not a primitive or very "small" type.

+3
source share

To do anything other than declare a pointer to an object, you need a full definition.

The best solution is to move the implementation to a separate file.

If you must keep this in the header, move the definition after both declarations:

 class tile_tree_apple; class tile_tree : public tile { public: tile onDestroy(); tile tick(); void onCreate(); }; class tile_tree_apple : public tile { public: tile onDestroy(); tile tick(); void onCreate(); tile onUse(); }; tile tile_tree::onDestroy() {return *new tile_grass;}; tile tile_tree::tick() {if (rand()%20==0) return *new tile_tree_apple;}; void tile_tree::onCreate() {health=rand()%5+4; type=TILET_TREE;}; tile tile_tree_apple::onDestroy() {return *new tile_grass;}; tile tile_tree_apple::tick() {if (rand()%20==0) return *new tile_tree;}; void tile_tree_apple::onCreate() {health=rand()%5+4; type=TILET_TREE_APPLE;}; tile tile_tree_apple::onUse() {return *new tile_tree;}; 

Important

You have a memory leak:

 tile tile_tree::onDestroy() {return *new tile_grass;}; 

will create an object on the heap that you cannot subsequently destroy unless you make some ugly hack. In addition, your object will be chopped. Do not do this, return the pointer.

0
source share

To execute *new tile_tree_apple must be called, but at this point the compiler does not know anything about tile_tree_apple , so it cannot use the constructor.

If you put

 tile tile_tree::tick() {if (rand()%20==0) return *new tile_tree_apple;}; 

in a separate cpp file that has a tile_tree_apple class definition or includes a header file that has a definition, everything will work fine.

0
source share

I am CPP noob, but you do not need to specify inheritance in the declaration?

class tile_tree_apple : public tile;

-2
source share

All Articles