Forward declarations and Invalid uses of incomplete type Init

Alright, I don't know why I should have unresolved dependency issues here, but here goes:

And to think, I was just trying to build a simple class for initializing SDL facilities.

All the tutorials I've been doing (lazyfoo) seem really cluttered and have all this initialization data up-front in nested if-statements in main.cpp, and I thought it looked sloppy and that I'd do one better by encapsulating all that crap into a simple class for my own uses.

Having done thirty of them, I thought I knew enough to start screwing around on my own. Maybe not?

Init.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>

class Init()
{
    public:
    bool initAll();
    bool initVid();
    void initVSync();
    void initLinTextFilt();
    bool initWindow(SDL_Window* winArg);
    bool initRenderer(SDL_Window* winArg, SDL_Renderer* rendArg)
    bool initTTF();
    bool initIMG();
};



(Ignore the "magic consts" in the window creation function, they're just placeholders for variables I have yet to declare.)
Init.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
#include "Init.h"

//calls all other Initialization functions
bool Init::initAll(SDL_Window* window, SDL_Renderer* renderer)
{
    initVid();
    initVSync();
    initLinTextFilt();
    initWindow(window);
    initRenderer(window, renderer);
    initTTF();
    initIMG();
}
//Initialize SDL Video subsystem
bool Init::initVid()
{
    bool success = true;
    if(!SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        printf("SDL_INIT_VIDEO failed. SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    return success;
}
//Initialize vertical synchronization
void Init::initVSync()
{
    if(!SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"))
    {
        printf("Warning: VSync not enabled.");
    }
}
//initialize linear texture filtering
void Init::initLinTextFilt()
{
    if(!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
    {
        printf("Warning: Linear texture filtering not enabled.");
    }
}
//initialize window
bool Init::initWindow(SDL_Window* winArg)
{
    bool success = true;
    winArg = SDL_CreateWindow("Default Title", SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
    if(winArg == NULL)
    {
        printf("Window could not be created! SDL error: %s\n", SDL_GetError())
        success = false;
    }
    return success;
}
//initialize renderer
bool Init::initRenderer(SDL_Window* winArg, SDL_Renderer* rendArg)
{
    bool success = true;
    rendArg = SDL_CreateRenderer(winArg, -1, SDL_RENDERER_ACCELERATED);
    if(gRenderer == NULL)
    {
        printf("Renderer could not be created! SDL error: %s\n", SDL_GetError())
        success = false;
    }
    else
    {
        SDL_SetRenderDrawColor(rendArg, 0x00, 0x00, 0x00, 0xFF);
    }
}
//Initialize TrueType Font subsystem
bool Init::initTTF()
{
    bool success = true;
    if( TTF_Init() == -1 )
    {
        printf( "SDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError() );
        success = false;
    }
    return success;
}
//Initialize PNG loading subsystem
bool Init::initIMG()
{
    bool success = true;
    int imgFlags = IMG_INIT_PNG
    if (!(IMG_Init(imgFlags)&imgFlags))
    {
        printf("SDL_Image could not initialize! SDL_Image Error: %s\n", IMG_GetError() );
        success = false;
    }
    return success;
}


main.cpp
1
2
3
4
5
6
7
8
9
10
11
#include "Init.h"

//global vars
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;

//main execution
int main(int argc, char* [] args)
{
    initAll(gWindow, gRenderer);
}



build messages (backspaced over long directory names for convenience)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dir\Init.h|6|error: expected unqualified-id before ')' token|
dir\Init.cpp|4|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|15|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|26|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|34|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|42|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|55|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|70|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
dir\Init.cpp|81|error: invalid use of incomplete type 'class Init'|
dir\Init.h|6|error: forward declaration of 'class Init'|
||=== Build finished: 17 errors, 0 warnings (0 minutes, 0 seconds) ===|
Look at line 14 of Init.h. There's something missing...
A couple of things jump off the page:

- The brackets on line 6 of Init.h shouldn't be there,
- The declaration and definition of initAll don't match (one has no parameters, the other has two parameters)
Thanks a ton guys. Sometimes I just need a second pair of eyes that aren't tired.

I gotta leave for work now, but I'll take your advice when I get back!

Thanks in advance for any additional help.
Line 6 of Init.h:

1
2
3
4
5
6
7
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>

class Init //() <- you don't put parenthesis on class definitions.  Only for functions.
{


Also these are non-static members of a class, so you need to have an object to act on.

1
2
3
4
5
6
7
int main(int argc, char* [] args)
{
    // initAll(gWindow, gRenderer);  <- won't work because initAll isn't global

    Init obj;  // <- have to create an Init object
    obj.initAll( gWindow, gRenderer );
}


But of course... having an 'Init' object doesn't really make much sense. Can you have multiple Inits? Does having the object actually do anything?

These functions are all global by nature. Rather than putting them in a class, maybe put them in a namespace:

1
2
3
4
5
6
7
8
9
10
11
12
namespace Init
{
   bool initAll();
   ...
}

//...

int main()
{
    Init::initAll( ... );
}


Or... if you don't want a namespace... then make it a static class that can't be instantiated (though that is more work for little gain).




Remember the whole point of a class is to represent a 'thing'. They're nouns.

Common examples of classes and what they represent:
std::string - represents a string
std::fstream - represents a file
std::list - represents a linked list of objects
etc

What exactly does an 'Init' represent? It's not a 'thing', so it doesn't really need to be a class.
Ah, thank you Disch. I wasn't sure if classes NEEDED objects or not and I had forgotten about creating namespaces. I thought it was conventional to have objects of classes, but not mandatory. I had tried converting it to a struct before posting this thread, but obviously that didn't work.

And I had thought about making an Init object (which would require me to write a constructor) but it occurred to me, like you said in your post, that it made no sense.

I'll eventually remember all this if I fail enough times. :P

EDIT:

Disch! I noticed in your namespace example that you put the namespace Init member functions in main, is that truly necessary? The whole reason I decided to do this whole wrapper class thing was to keep excess stuff out of main. Should I define the functions inside the namespace, instead? Will that create problems because it's inside a header?

Edit 2: Never mind the previous edit. Everything is in order now.
Last edited on
Topic archived. No new replies allowed.