0

I'm making a c++ OpenGL project and I'm having trouble with static variables.

I have a header "Scene.h" like so:

#pragma once

#include "A.h"

class Scene
{
    //class body
};

static Scene* active = new Scene();

And my A.h file looks like this:

#pragma once

#include "Scene.h"

class A
{
    active->SomeMethod(); //Here I get error C2065: undeclared identifier
};

In my source file I have included only my Scene.h, since it includes A.h already, and I have no problem there.

I have also tried to use a static Scene object like so:

class Scene
{
    static Scene* active;
};

And then to access it like so:

Scene::active->DoSomething();

But then I get error C2653: Scene is not a class or namespace name. I read somewhere that to do this I need precompiled headers, and that is no option for me.

What is the correct way to have a static pointer in this case?

6
  • 1
    The class definition contains members of the class, not active->SomeMethod(); (whatever that is meant to be) Commented Dec 6, 2019 at 8:00
  • 1
    If you want static variables in header, make them inline static. However, I really believe you want inline extern Scene* active = new Scene();. Commented Dec 6, 2019 at 8:00
  • 1
    The best way to deal with static variables in system programming languages is to only have values that are read-only. Right now you're experiencing linking issues and more. There is also no good way to write unit tests for code that deals with static variables. If you need variables that can be modified at runtime, I advise to never give them static lifetime. For debugging purposes, sure, but otherwise it is bad practice. Small fact : in Rust the compiler with default settings will only allow read-only variables to have static lifetime. Commented Dec 6, 2019 at 8:08
  • 2
    Btw. there is a circular dependency of A.h and Scene.h (that I bet is the reason of C2653: Scene is not a class or namespace name). Whatever is read first, reads the other which then tries to read the first but fails (due to the #pragma once). One of these two #includes has to be removed (and replaced by a forward declaration in case). Please, have a look at this: SO: C++ circular header includes Commented Dec 6, 2019 at 8:08
  • By the way, in 'C++' read-only variables start with the const keyword. Commented Dec 6, 2019 at 8:14

2 Answers 2

1

If you declare a global variable static in C++, you make it internal linkage. This means, it is not visible to other compilation units, and since you want to use it in class A - which probably resides within a different source file - this is not what you want.

What you probably want is a static class member (your second example), but be aware that in addition to the declaration you need to define it:

class Scene
{
    public:
       static Scene* active;
};

Scene* Scene::active = new Scene();

Also note that members of C++ classes by default are private, so your second example is lacking the public access specifier, so A would not be able to access a private member of Scene.

As Scheff has already pointed, you're having issues with circular dependencies. If class Scene does not use A in any way, remove #include "A.h" in the "Scene.h". Otherwise move active->SomeMethod(); to the implementation of class A and use forward declaration instead of including "Scene.h" in A.h.

[edit] As a note, since you only show excerpts of your code: This answer was written under the assumption that you have a header file and a source file for Scene, and a header file and a source file for A. If you keep both Scene and A within their headers only, things will not work out because of circular dependencies. Unless you have a strong reason for going header-only, I would suggest in any case that you have a clean separation between clas declaration (header file) and implementation (source file), avoid too many mutual includes if possible and rather use forward declarations.

Sign up to request clarification or add additional context in comments.

2 Comments

I am getting "explicit type is missing" when I try to put static in front of Scene::active = new Scene().
sorry, copy & paste error. I've corrected it. There shall be no static in the definition, but the return type (Scene*) instead.
0

See working example (by the use of the hint from scheff) in onlineGdb.

First of all I do not recommend use of global variables! Even worse is there use at global namespace. Better design is some namespace or if applicable (acessed only from one file) definition in an anonymos namespace. Think about using the singleton-Pattern - but that does not adress your Question.

Second I do not recomend to use a raw pointer: Objects you created with new you have to destroy, but at which time you'll want to do it. If ever You stick to a pointer use some smartpointer ... - My enhancment uses an Objecte, and prove by cout the call of the destructor.

the Prob in your code is: You can't call a method inside a class definition.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.