Declaring object of a class in another class

This is my first post and I'm thankful for all of your answers. I'm learning C++ with an online book and I came to the part were OOP is being explained. I pretty much understand the way it works, but it seems that I don't understand an important part.

Information:
I'm using Code::Blocks v12.11.
(I'm using C++/SDL2, but I think that's of no relevance)


Problem:
I create a class named "CSprite" in a "Sprite.hpp"-file. I create a "Sprite.cpp"-file, which includes the "Sprite.hpp"-file. I define the methods of the class "CSprite" in the "Sprite.cpp"-file.
When I try to create an object of "CSprite" in the class named "CPlayer" in the file "Player.hpp" I get an error message. (<-- Looks complicated I know, the code example will be more usefull than this)

Error in the build messages:
C:\Users\Lino\Documents\1 Data Lino\Freizeit\1 Programmieren\C++ & SDL2\The Running Man\CPlayer.h|30|error: 'CSprite' does not name a type|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 1 seconds) ===|

Code Example:

Sprite.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef _SPRITE_HPP_
#define _SPRITE_HPP_

class CSprite
{
    public:
        CSprite();
        void Load(...);
        void Render(...);
        ...
    
    private:
        SDL_Texture* example;
        ...

};


Sprite.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "Sprite.hpp"
#include <iostream>
#include "SDL.h"

CSprite::CSprite()
{
    example = NULL;
    ...
}

void CSprite::Load(...)
{
    ...
}

void CSprite::Render(...)
{
    ...
}


Player.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef _PLAYER_HPP_
#define _PLAYER_HPP_

#include "Sprite.hpp" //<--include the Header where the class is

class CPlayer
{
    public:
        CPlayer();
        void Load (...);
        ...

    private:
        float fXPos;
        float fYPos;
        ...
        CSprite PlayerSprite; //<-- Here is the error message

};

#endif //_PLAYER_HPP_ 



Player.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Player.hpp"
#include <iostream>
#include "SDL.h"

CPlayer::CPlayer()
{
    ...
}

void CPlayer::Load(...)
{
    PlayerSprite.Load(...); //<-- Use the "CSprite"-class method called "Load(...)"
}



What did I miss? Did I include the wrong file? Or did I Forget to include the file? Why do I get the error message?


I guess it's something pretty easy that I have overlooked, but I still can't figure it out after two days of searching trough Forums and reading tutorials about OOP in C++. I also tried it with a pointer declaration and the "->" Operator but I got the same error message.

I know I could just write a new function to load the texture in my "CPlayer"-class but this would not really answer my question.

When you give me any tips, I'd appreciate if you explain me why that happens (very, very short / link to a page explaining my Problem) or where to change something (in which line of the code / or where to change something with Code::Blocks).

If necessary I could post/send you all of my code...

Thank you for your help in advance...

Cheers Half_NO_oB
I don't see anything obviously wrong but it's hard to tell without seeing the real code. The error message mentions CPlayer.h but in your code you have use Player.h.
+1 for needing to see your actual code. +100 for making such a great first post btw
I only see one thing that looks wrong, but I don't think it'd cause your problem:
You're missing #endif //_SPRITE_HPP_ .

Another idea... Do you have a default constructor, or is it possible that it's being confused with another constructor? If so try this in your constructor:
1
2
3
4
5
CPlayer::CPlayer()
 : PlayerSprite( CSprite() )
{
    ...
}


Worst case scenario, in case you can't figure it out do it this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class CPlayer
{
public:
    CPlayer();
    ~Cplayer();
    ...
private:
    CSprite* PlayerSprite;
    ...
};
...
CPlayer::Cplayer()
{
   PlayerSprite = new CSprite();
}

CPlayer::~CPlayer()
{
    delete PlayerSprite;
}

void CPlayer::Load(...)
{
    PlayerSprite->Load(...);
}
Last edited on
Wow this was fast :D. Sorry I took so long, but I had to clean that messy code of mine up.

@Peter87:
The code up there just serves as an example. The file in my Project is called "CPlayer.h" ;)

@Little Bobby Tables
Thanks!

@Stewbond
Aaargh! You found a mistake... This is also en error who happens to be there because I wrote the code example and didn't copy it out of my project. I did not learn much about inheritance (it is inheritance in your example isnt it?). I do not have something like a Default constructor... And I don't have a constructor with the same name (if thats what you mean by confuse)...


There are some SDL-funtions within the code, but I guess you can just ignore them, since they don't have much to do with the errors.


Actual Code:
So here are the four files I actually use in my project (they aren't even close to being finished yet).

CSprite.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef _CSPRITE_H_
    #define _CSPRITE_H_

#include "SDL.h"
#include "SDL_image.h"
#include "CGame.h"

class CSprite
{
    public:
        CSprite();

    public:
        void Load(const char* cPath, int R, int G, int B);
        void Render ();

    private:
        SDL_Rect rcDest;
        SDL_Surface* sImage;
        SDL_Texture* tImage;

        CGame Game; //<-- Creates error message no 1)

};


#endif // _CSPRITE_H_ 


1) Error: 'CGame' does not name a type

CSprite.cpp
#include "CSprite.h"
#include <iostream>

CSprite::CSprite()
{
sImage = NULL;
tImage = NULL;

}


void CSprite::Load (const char* cPath, int R, int G, int B)
{
sImage = IMG_Load(cPath);
if (sImage == NULL)
{
std::cout << "Fehler beim Laden von " << cPath << "! SDL_Error: " << SDL_GetError() << "\n";
}
else
{
SDL_SetColorKey(sImage, SDL_TRUE, SDL_MapRGB(sImage-> format, R, G, B));
tImage = SDL_CreateTextureFromSurface(Game.GetRenderer(), sImage); //<-- Creates error message no 2)
if (tImage == NULL)
{
std::cout << "Fehler beim Umwandeln von einer Surface in eine Textur der Grafik " << cPath << "! SDL_Error: " << SDL_GetError() <<"\n";
}
SDL_FreeSurface (sImage);
}
}



void CSprite::Render()
{
SDL_RenderCopy (Game.GetRenderer(),tImage,NULL,&rcDest); //<-- Creates error message no 3)
}
[/code]

2) Error: Game was not declared in this scope
3) Error: Game was not declared in this scope


CPlayer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _CPLAYER_H_
    #define _CPLAYER_H_


#include "CSprite.h"
#include "CGame.h"
#include <string>


class CPlayer
{
    public:
        CPlayer();

    public:
        void Init();
        void Render();


    private:

        CSprite SpritePlayer; //<-- Creates error message no 4)


};


#endif // _CPLAYER_H_ 


4) Error: 'CSprite' does not name a type


CPlayer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "CPlayer.h"
#include "CGame.h"



CPlayer::CPlayer()
{

}

void CPlayer::Init()
{
    SpritePlayer.Load("data/imgs/player/Ash_Player.bmp", 255, 0, 255); //<-- Creates error message no 5)
}



void CPlayer::Render()
{
    SpritePlayer.Render(); //<-- Creates error message no 6)

}


5) Error: SpritePlayer was not declared in this scope
6) Error: SpritePlayer was not declared in this scope


(Somehow the "Preview"-Button is not working. Hope it doesn't look too bad in the real post)


Thank you for all the fast answers so far!

Cheers Half_NO_oB
Yep, they all chain from the first error. Always debug the first one first.

CGame isn't a type, so Game is never resolved.

Since Game is never resolved, CSprite doesn't end up being defined.

Since CSprite isn't defined, SpritePlayer isn't really created.

What's in your CGame.h? The problem would be in there.
@Stewbond
Makes sense :D


Here another bit of code:
(It may seem a bit too much to create this many small classes but I plan on extending them to a Framework... and I guess that will be a lot easier when I just have to extend classes)

CGame.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef _CGAME_H_
    #define _CGAME_H_


#include "SDL.h"
#include "SDL_image.h"


class CGame
{
    public:
        CGame();


    public:
        bool OnInit();
        void OnEvent(SDL_Event* Event);
        void OnLoop(); //Data Updates
        void OnRender();
        void OnCleanup();

        int GetScreenWidth();
        int GetScreenHeight();

        SDL_Renderer* GetRenderer();

        bool bRunning; //<-- Should be private I know ;D

    private:
        int SCREEN_WIDTH;
        int SCREEN_HEIGHT;
        SDL_Window* MainWindow;
        SDL_Renderer* MainRenderer;
        SDL_Surface* MainWindowSurface;
};


#endif // _CGAME_H_ 


CGame.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "CGame.h"
#inlcude "CMap.h"
#include "CSprite.h"

CGame::CGame()
{
    bRunning = true;

    SCREEN_WIDTH = 640;
    SCREEN_HEIGHT = 480;

    MainWindow = NULL;
    MainRenderer = NULL;
    MainWindowSurface = NULL;

}


bool CGame::OnInit()
{
    CSprite sprite;

    if (SDL_Init (SDL_INIT_EVERYTHING) < 0)
    {
        std::cout << "SDL could not be initialized! SDL_Error: " << SDL_GetError ();
    }
    else
    {
        MainWindow = SDL_CreateWindow ("The Running Man",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_SHOWN);
        if (MainWindow == NULL)
        {
            std::cout << "SDL could not create the window! SDL_Error: " << SDL_GetError () << "\n";
        }
        else
        {
            MainRenderer = SDL_CreateRenderer(MainWindow, -1, SDL_RENDERER_ACCELERATED);
            if (MainRenderer == NULL)
            {
                std::cout << "SDL could not create the renderer! SDL_Error: " << SDL_GetError() << "\n";
            }
            else
            {
                MainWindowSurface = SDL_GetWindowSurface(MainWindow);
                if (MainWindowSurface == NULL)
                {
                    std::cout << "SDL could not get the window surface! SDL_Error: " << SDL_GetError() << "\n";
                }
            }
        }
    }
    return true;
}


void CGame::OnEvent(SDL_Event* Event)
{
    if(Event->type == SDL_QUIT)
    {
        bRunning = false;
    }
}


void CGame::OnLoop()
{

}

void CGame::OnRender()
{

    SDL_SetRenderDrawColor(MainRenderer,0,0,255,255);

    SDL_RenderPresent(MainRenderer);

}

void CGame::OnCleanup()
{
    SDL_FreeSurface (MainWindowSurface);
    SDL_DestroyWindow (MainWindow);
    SDL_DestroyRenderer (MainRenderer);

    SDL_Quit ();
}

int CGame::GetScreenHeight()
{
    return SCREEN_HEIGHT;
}

int CGame::GetScreenWidth()
{
    return SCREEN_WIDTH;
}

SDL_Renderer* CGame::GetRenderer()
{
    return MainRenderer;
}



Here it is :D I hope that helps. I'm sorry but I will be able to repost something new tomorrow evening...

Good evening and Cheers Half_NO_oB
i think i see the issue. which is included first in main.cpp? CGame.h or CSprite.h?
In these cases where are several files, I would prefer if you could upload all of them to github or similar, so I don't have to work to replicate your setup.

I can compile `CPlayer.cpp' and `CSprite.cpp' fine.
you've got a typo in line 2 of CGame.cpp, and there are missing headers.


Apart from that, ¿why does an sprite own a game? maybe you wanted a reference instead



> Worst case scenario, in case you can't figure it out do it this way:
Missing forward declare
Missing copy constructor and assignment operator
And it's just awful http://www.cplusplus.com/forum/general/138037/
thats what i was thinking ne555. it seems like (s)he has circular dependencies with csprite and cgame, so just needs to forward which is declared second
Albeit the `does not name a type' error may come from a circular inclusion, what was posted does not show that.

The headers seem to be well done, so the inclusion order would be irrelevant. Just to be sure I created an empty main and tried different inclusion orders for the headers, and it compiled fine.


> so just needs to forward which is declared second
Not sure what you meant. You can forward declare if you only have pointer or references (and you do not try to access members with them)
sorry im not sure what i was thinking. i was tired when i posted that
@n555
Thank you :D Fixed the headers up...

@Stewbond
I tried out that worst case scenario way of yours. I ended up getting the same errors :(

@Little Bobby Tables
I don't quite get what you mean by “just needs to forward which is declared second” :o

I googled the “circular dependencies” you mentioned and it seems to be connected to the forward declaration. I guess I really do use those circular dependencies, but what does that mean for me? It seems to be dangerous under certain circumstances…

I reckon that the easiest way is to submit the whole Project to github... I will cut down the project even more to its essentials to keep it (as) clean (as possible).

But first I have to figure out how to upload it to github ^^’

~~~~~2hours later~~~~~

Goddamn that took way too much time in my opinion :@@@


I hope it worked out just fine...

Link:
https://github.com/HalfNOobe/TheRunningMan


Thanks for your efforts :3 :*

Cheers Half_NO_oB
ignore me. i was being stupid. if you would like a tutorial, hop on #cplusplus (an irc channel from irc.quakenet.org) and i would love to give you a tutorial for it
Yep, circular includes. (which your testcase in this thread did not reproduce)
Please refer to http://www.cplusplus.com/forum/articles/10627/

There is no reason for `CGame.h' to include `CPlayer.h'
There is no reason for `CPlayer.h' to include `CGame.h'
In `CSprite.h' a forward declaration should be enough
`CSprite.cpp' tries to access members, so it needs to include `CGame.h'

Here you are https://github.com/ne555/TheRunningMan
@ne555
>There is no reason for 'CGame.h' to include 'CPlayer.h'
You are absolutly right. There is no reason to include 'CPlayer.h' right now, forgot to cut it out. Later on I will put the CPlayer::Load() in the CGame::Init() and the CPlayer::Render() into the CGame::Render() function, and then it will be needed.


The code you uploaded works perfectly fine! :D

Thank all of you and especially ne555 for even fixing my Project. I see that I still have a long way to go :)

Cheers Half_NO_oB
Topic archived. No new replies allowed.