I'm creating a simple game in SDL2 and learning about C++ classes, however I'm having difficulty with private variables and class constructors. I'm attempting to access an SDL_Texture that is defined as a private variable and modify it within the constructor.
Upon compilation the code below causes the following error:
In constructor 'PlayerShip::PlayerShip(SDL_Texture*)':
|5| error: 'ShipSprite' was not declared in this scope
Header file (PlayerShip.h):
#ifndef PLAYERSHIP_H
#define PLAYERSHIP_H
#include "SDL2/SDL.h"
class PlayerShip
{
public:
PlayerShip(SDL_Texture * tex);
private:
SDL_Texture * ShipSprite = nullptr; //The variable/texture I want to modify
};
#endif
CPP file (PlayerShip.cpp)
#include "PlayerShip.h"
PlayerShip::PlayerShip(SDL_Texture * tex) //ctor
{
ShipSprite = tex; //This needs to change the private variable above. However "ShipSprite" is apparently not in scope.
}
It is defined in the header, however I'm not sure why it won't access it even though it's inside the class. I've tried searching for solutions to this problem, however the ones I found were not related to my issue.
On top of this, I've tried changing ShipSprite = tex; to the following but with no success:
PlayerShip::ShipSprite = tex; and
this->ShipSprite = tex;
Any ideas for this would be appreciated. Thanks.
Depending on how recent your compiler is, it may not accept initialization of a non-static member that doesn't have integer type. Or it may not know the keyword nullptr.
SDL_Texture * ShipSprite = nullptr;
Try instead
SDL_Texture * ShipSprite;
See if you don't define the include guard (#ifndef PLAYERSHIP_H) somewhere else.
Also, check the output of minGW, which files it uses, maybe your assumptions are wrong? You can also do quick and dirty debug things like introducing a syntax error in your header file. If it isn't caught, the file isn't even used.
Other than that I'd suggest a few other things (unrelated to your question):
Have a naming convention for member variables that is different from that of class names. ShipSprite could be shipSprite_, m_shipSprite, shipSprite, or what have you. (A good set of recommendations: http://geosoft.no/development/cppstyle.html)
If you want to initialize member variables, prefer to do so with the constructor initializer list. I.e.:
PlayerShip::PlayerShip(SDL_Texture * tex) : ShipSprite(tex) {
} The compiler might be more helpful if you are more precise in what you want to do.
It would appear that I may have accidentally compiled the header file separately before I added the variable, and it left a PlayerShip.gch file in the same folder as my headers. GCC probably tried to use it instead of the normal header file and thus gave me that error.
Nonetheless deleting the .gch file seems to have fixed the issue for me and now the program compiles properly. Not sure how I completely missed that.
Thanks again everyone for your suggestions and help.
Edit: How do I go about closing this?
Related
I came across this error when running make on a large project using gcc5.4.0.
/usr/include/c++/5/sstream:300:14: error: '__xfer_bufptrs' redeclared with 'public' access
struct __xfer_bufptrs
^
/usr/include/c++/5/sstream:67:14: note: previously declared 'private' here
struct __xfer_bufptrs;
To me it seems like an issue with the compiler? Since the issue arises in a standard c++ library sstream? It does not make sense to me, am I using a wrong compiler?
Here are the code snippets the error messages refer to:
1.) sstream starting at line 67
class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
{
struct __xfer_bufptrs;
public:
2.) sstream at line 300
#if _GLIBCXX_USE_CXX11_ABI
// This type captures the state of the gptr / pptr pointers as offsets
// so they can be restored in another object after moving the string.
struct __xfer_bufptrs
{
__xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to)
: _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1}
{
I know there cannot be anything wrong with the standard library so why is it throwing an error?
This is the closest I got to some answer:
https://github.com/PacificBiosciences/pbbam/issues/14
And it seems the answer revolves around these "Dprivate" and "Dpublic" flags. Which I assume are compiler flags, but I'm not sure what they do.
Although the thread at github hits the spot, it seems to miss the reason. You most likely are building some unit or other tests in your project that redefine the 'private' keyword like so:
#define private public
Or do the respective thing via command like (-Dprivate=public). This is a commonly used practice to expose private members for testing without making the tested code dependent on the testing code.
However look at your snippets. The first one declares __xfer_bufptrs as private regardless of your definition of private. Next second snippet is surely (haven't checked though) in an explicit private block. Now if your definition of private is in place you will ned up with public in the second snippet which is a fault.
You have at least two options, other are surely also possible:
You #undef the private definition before including system headers and define again after inclusion of those, or
You use another macro to define your own private/public sections e.g.: #define my_public public which can be redefined at will. This solution seems icky though ;)
Oh and for the future in your own code always use explicit access qualification to avoid this sort of mess at least with your own code :)
I just encountered a strange issue. In WinMain.cpp, AFTER I include a user-created header file, but BEFORE WinMain, I declare a global instance of my class Brain, like so:
(windows includes)
#include "BrainLib.h"
#include "Brain.h"
Brain brain;
(wndproc declaration)
WinMain() {
(some code using Brain)
}
In BrainLib.h, I declare some constants for general program use, such as const unsigned short SERVER_PORT = 12345; and const std::string SERVER_IP_STRING = "192.168.1.104"; Note that Brain.h also includes BrainLib.h
Now here it gets interesting. Brain contains a Winsock client wrapper class that will only connect to one server. Thus, the Winsock client has a constructor requiring a port/ip and no default constructor. So, it must be initialized in the Brain constructor initialization list like so:
Brain::Brain() : winsockClient( SERVER_PORT, SERVER_IP_STRING )
{
}
However, SERVER_IP_STRING is still uninitialized when the Brain constructor is called! I put a check in WinMain, and it's constructed at that point, but it seems as though the Brain constructor is called first, even though it appears second. How/why can this be?
Also, just to make this stranger: I copied the source and compiled on a different machine, and it worked as expected. Same version of MSVS 2008 running on each, though I suppose possibly with some sort of different build settings.
The order in which global objects are initialized is undefined.
I've got an enum type defined in the private section of my class. I have a member of this type defined as well. When I try to initialize this member in the constructor body, I get memory corruption problems at run-time. When I initialize it through an initialization list in the same constructor instead, I do not get memory corruption problems. Am I doing something wrong?
I'll simplify the code, and if it is a GCC bug I'm sure that it's a combination of the specific classes I'm combining/inheriting/etc., but I promise that this captures the essence of the problem. Nothing uses this member variable before it is initialized, and nothing uses the newly created object until after it is fully constructed. The initialization of this member is indeed the first thing I do in the body, and when the memory corruption happens, valgrind says it is on the line where I initialize the variable. Valgrind says that it is an invalid write of size 4.
Pertinent header code:
private:
enum StateOption{original = 0, blindside};
StateOption currentState;
pertinent .cpp code (causes memory corruption and crash):
MyClass::MyClass(AClass* classPtr) :
BaseClass(std::string("some_setting"),classPtr)
{
currentState = original;
...
}
pertinent .cpp code (does not cause memory corruption and crash):
MyClass::MyClass(AClass* classPtr) :
BaseClass(std::string("some_setting"),classPtr),
currentState(original)
{
...
}
edit: see my "answer" for what was causing this. After reading it, can anybody explain to me why it made a difference? I didn't change anything in the header, and obviously the object file was being rebuilt because of my print statements appearing when I put them in and the lack of seeing the bug under one build but not the other?
For a good explanation, I'll mark it as the answer to this question.
For posterity:
It appears as though the make script isn't pickup up the changes to these files for some reason. Manually deleting the objects rather than letting our "clean" target in the makefile caused a full rebuild (which took some time), and the problem disappeared.
I have a class like this:
class Player
{
public:
Player(Board * someBoard);
void setSide(char newSide);
protected:
Board * board;
char side;
};
and its implementation is as such:
Player::Player(Board * someBoard)
{
board = someBoard;
side = '0';
}
void Player::setSide(char newSide)
{
side = newSide;
}
Now I have another class inheriting from it:
class HumanPlayer : public Player
{
public:
HumanPlayer(Board * someBoard);
};
And its short implementation is this:
HumanPlayer::HumanPlayer(Board * someBoard) : Player(someBoard)
{
}
Now the problem is the side = '0'; line makes the program freeze (the window turns white in Windows 7, not sure if that means it froze or crashed). Commenting it out make the program run fine (and it's okay to comment it out because the variable isn't used anywhere yet).
What is causing the error and how can I fix it?
EDIT!
After printing out some stuff to an fstream, all of a sudden the program worked. I tried commenting the printing out. It still worked. I tried deleting the debugging code I added in. It still worked. So now my code is exactly the same as listed above, but it magically works now.
So what do I do now? Ignore the anomaly? Could it have been a compiler mistake?
I suspect the problem isn't what you think it is.
It sounds like a memory corruption issue of some sort, but it's really impossible to tell based on the information provided. I have two suggestions for you:
Either post the smallest complete program that demonstrates the problem, or
Try a valgrind-type tool to see if it helps you figure out what's going on.
Or, better yet, start by looking at the state of the program in the debugger (once it's hung.)
Is it possible that you are using two incompatible definitions of your Player class, defined in different header files? If the definitions have different sizes, then the 'size' member might lie outside the memory block allocated for the class instance.
Edit I see that your problem has disappeared. So it was probably a module that didn't get re-compiled after a change in the class definition; but now that you've re-compiled everything, the problem has fixed itself.
I have a header file with some inline template methods. I added a class declaration to it (just a couple of static methods...it's more of a namespace than a class), and I started getting this compilation error, in a file that uses that new class.
There are several other files that include the same .h file that still compile without complaint.
Googling for the error gives me a bunch of links to mailing lists about bugs on projects that have a similar error message (the only difference seeming to be what the constructor, destructor, or type conversion is supposed to precede).
I'm about ready to start stripping everything else away until I have a bare-bones minimal sample so I can ask the question intelligently, but I figured I'd take a stab at asking it the stupid way first:
Can anyone give me a basic clue about what this error message actually means so I might be able to begin to track it down/google it?
Just for the sake of completeness, the first example of where I'm seeing this looks more or less like
namespace Utilities
{
template <typename T> GLfloat inline NormalizeHorizontally(T x)
{
GLfloat scaledUp = x*2.0;
GLfloat result = scaledUp / Global::Geometry::ExpectedResolutionX;
return result;
}
}
It means that you put the "inline" keyword in the wrong place. It needs to go before the method's return type, e.g.
template <typename T> inline GLfloat NormalizeHorizontally(T x)
Simple as that.
The reason that you got this message on one compilation unit and not others may be because it is a templated function that was not being instantiated from those other compilation units.
Generally, if you get an "expected blah blah before foobar" error, this is a parsing error and it often indicates a simple syntax mistake such as a missing semicolon, missing brace, or misordered keywords. The problem is usually somewhere around the portion mentioned, but could actually be a while back, so sometimes you have to hunt for it.