I've created a structure in a header file as follows:
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
which works without a problem.
However, in that particular header file, I want to declare a global emitter that I can use in all the functions and isn't part of the main source file:
// header.h global declaration
emmiter currentEmit;
GLvoid glSetEmitter(emitter emitter)
{
currentEmit = emitter;
}
However, when I do try this, I get a whole lot of "error C2228: left of '.variable' must have class/struct/union, so I'm assuming it's not declaring my structure here at all.
Is there a way to declare that structure globally within a header file, and if so, is there also a way to keep it from being part of the other .cpp files as well?
emitter is not the same as emmiter.
Also, since this is C++ - just write struct {}; directly, there's no need for a typedef.
Your whole header is wrong, and will give multiple definitions if included in multiple translation units:
// header.h global declaration
extern emitter currentEmit; // <-- note extern
inline GLvoid glSetEmitter(emitter emitter) // <-- note inline
{
currentEmit = emitter;
}
currentEmit needs to be defined in a single implementation file, not a header. The function needs to be inline so it's not defined by all TU.
Last thing: pass the parameter by const reference:
inline GLvoid glSetEmitter(const emitter& emitter) // <-- note inline
{
currentEmit = emitter;
}
Otherwise an unnecessary copy will be created.
typedef struct
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
} emitter;
should better be
struct Emitter
{
GLfloat lgtR, lgtG, lgtB, lgtA;
GLfloat x, y, z;
bool islight;
GLfloat width, height, depth;
GLenum lightn;
particle prt;
int maxprt;
};
Is there a way to declare that structure globally within a header file,
Yes, there are two main ways to avoid the variable being created in each compilation unit.
First there is the Meyers' singleton:
namespace g {
inline Emitter& emitter()
{
static Emitter theEmitter;
return theEmitter;
}
}
void foo() { g::emitter().x = 666; }
Then there is the templatization trick:
namespace detail {
template< class Dummy >
struct EmitterVariable
{
static Emitter v;
};
template< class Dummy >
Emitter EmitterVariable<Dummy>::v = {};
}
namespace g {
static Emitter& emitter = EmitterVariable<void>::v;
}
void foo{ g::emitter.x = 666; }
and if so, is there also a way to keep it from being part of the other .cpp files as well?
Yes, both of the above solutions do that.
The last one, however, injects a reference into each compilation unit, which in practice will be the size of a pointer.
That said, global variables tend to give very messy data flows. You don't know which part of the code put something there. You don't know if or when it's properly initialized. You don't know which other parts will be affected if you change data here. Or when. And so on. So it's absolutely not a good idea. Global constants, OK, but global variables, Just Say No™.
Related
I am trying to build a window controller for SDL with its own pseudo-pixels. I had the code working using a single big and ugly translation unit, but am now trying to refactor the same code into multiple units and classes.
In this class, I am attempting to define the controller for the window, and I am having trouble understanding how to work with a nested structure inside a class.
The errors I am getting are on the line Pixel* pixels[][];. The compiler complains that "incomplete type is not allowed". The struct seems to be fully defined in the .cpp.
The second error is that "an array may not have elements of this type"; I understand that the second dimension of an array has to be of a defined size, but how do I define this size at compile-time while keeping my code flexible for windows of different sizes?
//PxWindow.h
#include <SDL.h>
class PxWindow {
struct Pixel {
static int PARENT_PIXEL_SIZE;
// Data members
int x, y;
Color color;
// Methods
int screenX();
int screenY();
SDL_Rect getPixelRect();
};
// Private Data Member declarations
private:
int PIXEL_SIZE;
int NUM_PIXELS_X;
int NUM_PIXELS_Y;
// Public Data Member declarations
public:
Pixel* pixels[][];
SDL_Rect rects[][];
public:
PxWindow(int,int,int);
int getPixelSize();
int getNumX();
int getNumY();
};
// PxWindow.cpp
#include "PxWindow.h"
/*
* Pixel Structure method definitions
*/
SDL_Rect PxWindow::Pixel::getPixelRect() {
return SDL_Rect{ screenX(), screenY(), PARENT_PIXEL_SIZE, PARENT_PIXEL_SIZE };
};
int PxWindow::Pixel::screenX() { return x * PARENT_PIXEL_SIZE; }
int PxWindow::Pixel::screenY() { return y * PARENT_PIXEL_SIZE; }
/*
* PxWindow Class method definitions
*/
PxWindow::PxWindow(int px_size, int num_x, int num_y) :
PIXEL_SIZE(px_size),
NUM_PIXELS_X(num_x),
NUM_PIXELS_Y(num_y) {
Pixel::PARENT_PIXEL_SIZE = PIXEL_SIZE;
};
int PxWindow::getPixelSize() {
return PIXEL_SIZE;
};
int PxWindow::getNumX() {
return NUM_PIXELS_X;
};
int PxWindow::getNumY() {
return NUM_PIXELS_Y;
};
For the first error:
You should check your includes. Most likely one is missing to complete your struct "Pixel". You seem to use SDL_Rect, but I can't see the include for SDL in your header file.
For your second error:
To make the array a little more dynamic you would have to create a new array (arrayTwo) of array.size() + 1 and copy all data from array to arrayTwo yourself.
You could also use a (or two nested vectors for 2d), but it depends on your performance needs.
Why do I need to use :: to denote if a function is a member function but I don't need to do it for the instance variables? I do understand that :: is used to differentiate between standalone and member functions, but I still don't get the variables part. I'll give an example of what I'm talking about.
Shape.h
# pragma once
class Shape {
private:
int height;
int width;
public:
Shape(int height, int width);
int getHeight();
int getWidth();
}
Shape.cpp
#include "Shape.hpp"
Shape::Shape(int height, int width) {
this->height = height;
this->width = width;
}
int Shape::getHeight() {
return height;
}
int Shape::getWidth() {
return width;
}
Here, I have to to specify the class of the Shape constructor and the getters in order for the compiler to know what I'm talking about. So how come when I do return height; or this->height without specifying class it understands what I'm talking about.
C++ uses a model where it initially assumes everything is in the same namespace/class as what it's declared in unless stated otherwise. So, for example, if you write
int getHeight() {
return height;
}
at the top level of a C++ file, the compiler assumes you're declaring something in the global namespace. That means that getHeight is a free function. Then, the statement return height; is interpreted in the context of a free function in the global namespace - it'll start searching local variables for height, then global variables in the global namespace.
On the other hand, if you write
int Shape::getHeight() {
return height;
}
you're explicitly telling C++ "hey, I know that this code is in the global namespace at the top level, but I'm explicitly indicating that this is actually inside of the Shape class." At that point, the compiler says "ah, gotcha, you're inside Shape now" and interprets the code that's written as though it were inside Shape. In that sense, the statement return height; first starts looking for a local variable named height, then looks for a data member of Shape named height, then looks for global variables named height.
There's no fundamental reason why C++ had to do things this way, but there is a nice internal consistency to it. You stay at whatever "scope level" a statement or definition appears unless something explicitly moves you into a different scope level. So once you've declared the function in a way that says it's in Shape, everything inside it evaluates relative to Shape rather than to the global namespace.
Hope this helps!
but not variable. this is not true, you have to use :: if you want to get value outside the scope of the A class.
class A {
public:
const static int a = 5;
A (){}
};
int main (void) {
std::cout << A::a;
}
Simply put, I am trying to have textures and other semi-constant objects be prepared within one .h or .cpp file so that they can be used within other files. I want to be able to do something like this:
class Position
{
private:
int x;
int y;
public:
/* constructor, destructor, and other code */
void setPosition(int x, int y) { this->x = x;
this->y = y; }
};
Then, in another file, have something like this:
//otherfile.extension
// I want to be able to declare these objects here...
Position specialPosition1;
Position specialPosition2;
// ...and then be able to do this somewhere where it will keep
// this information for any other file that includes this.
specialPosition1.setPosition(25, 25);
specialPosition2.setPosition(-10, -10);
I want to be able to call their setPosition() method and prepare them within the same file to be used within other files if possible. Or at least be able to set it up so that the information will exist before it is used anywhere else.
If I recall, making them static would not solve this issue; plus I still have no (known) place to call the setPosition to prepare the objects. I have also read up a tad bit on extern, though my knowledge of it is only vague.
How might I be able to prepare these objects before main(), or, to be a bit more precise, what is the "best" way to prepare these objects before they are used in other files?
I don't think you want to call setPosition at all. I think it would be better to initialize them in the constructor. I assume these special positions are constant.
I think you want to declare them as extern in a .h file and then define them in a .cpp:
Position.h:
struct Position {
int x;
int y;
Position(int _x, int _y) : x(_x), y(_y) {}
//...
};
SpecialPositions.h:
#include "Position.h"
extern const Position specialPosition1;
extern const Position specialPosition2;
SpecialPositions.cpp:
#include "SpecialPositions.h"
const Position specialPosition1{25, 25};
const Position specialPosition2{-10, -10};
Main.cpp:
#include "SpecialPositions.h"
#include <iostream>
int main() {
std::cout << specialPosition1.x << "\n";
}
Or you could force compile time constants and use constexpr. Change the Position constructor to be constexpr:
constexpr Position(int _x, int _y) : x(x_), y(_y) {}
And then just define them in the SpecialPositions.h file (no need for SpecialPositions.cpp):
constexpr Position specialPosition1{25, 25};
constexpr Position specialPosition2{-10, -10};
I'm learning c++. I have written a small program which should compute the energy
of a N particle system. Up to now I have three small files:
data.h:
class Particle {
public:
double mass;
double charge;
double posx,posy,posz;
};
Particle part[2];
main.cpp:
#include <iostream>
#include "data.h"
using namespace std;
double energy(Particle part );
int main ()
{
double sd;
part[0].mass = 10.0;
part[4].mass = 90.0;
cout << part[0].mass << "\n";
cout << part[4].mass << "\n";
sd = energy(part);
cout << "sd" << sd << "\n" ;
return 0;
}
energy.cpp:
#include <iostream>
using namespace std;
double energy(Particle part)
{
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
I have two questions:
1)I want to make visible the Class particle in the function "energy". In other words,
I want to use the variables of the class function (with the values given in "main")
in the energy function.
I have tried as you see energy(Particle part) but it seems Particle is not defined
in that scope.
2)As you see in "data.h" I declared "part" as an array with two members. However,
in "main" I can use more than two members, for instance part[3],part[4]... Why I
could use more members than those I declared?
I am compiling with g++ -o test energy.cpp main.cpp
thanks.
1)I want to make visible the Class particle in the function "energy". In other words, I want to use the variables of the class function (with the values given in "main") in the energy function. I have tried as you see energy(Particle part) but it seems Particle is not defined in that scope.
If I understand you right.. You want to have
Particle part[2];
to be use able in main.cpp and in energy.cpp ?
If yes.. change this to:
extern Particle part[2];
and in energy.cpp add this:
#include "data.h"
Particle part[2];
and you will be able to use
double energy()
{
//main.cpp will have same part
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
2)As you see in "data.h" I declared "part" as an array with two members. However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
Because it's C/C++ ? no range checks. You can do what ever you want.
But if you do, the result will be unexpected.
1)I want to make visible the Class particle in the function "energy".
You should #include "data.h" in the file energy.cpp.
2)As you see in "data.h" I declared "part" as an array with two members.
You probably shouldn't have done that, for two reasons:
You will learn later to avoid declaring global objects. It is legal (and often correct) to do so, but until you learn, you probably want to declare it as a local variable in main.
You should not declare global objects in header files, since they will then be declared in every translation unit that includes the header file.
However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
By indexing beyond the end of the array, you have invoked "undefined behavior". The system is free to do almost anything (for example, crash, send Bill Gates an email, start a global thermo-nuclear war, &c). Among the infinite variety of things included in "undefined behavior" is the most confusing one of all -- appear to work. That is what happened in your case. You should not count on it continuing to appear to work.
All sorts of things you can do with a class ...
struct Vector3
{
double m_x, m_y, m_z;
};
class Particle
{
public:
double ComputeEnergy() { // return answer }
double GetMass() const { return m_mass; }
double GetCharge() const { return m_charge; }
const Vector3& GetPos() const { return m_pos; }
void SetMass(double mass) { m_mass = mass; }
void SetCharge(double charge) { m_charge = charge; }
void SetPos(const Vector3& pos) { m_pos = pos; }
void SetPos(double x, double y, double z)
{
m_pos.m_x = x;
m_pos.m_y = y;
m_pos.m_z = z;
}
private:
double m_mass;
double m_charge;
Vector3 m_pos;
};
You need to #include "data.h" in energy.cpp. Includes are only processed on a per-file basis, so energy.cpp can't see the header without that.
EDIT: In your function, the parameter part, out-scopes the global definition of part, so the part in your function is not an array. You want:
cout << part.mass << "\n";
1>Include "data.h" in energy.cpp
2> C++ array is very primitive it doesn't has any bound checking so you were able to access part[4].But there is no guarantee that it will work every time.Most of the time program may crash during run-time complaining the memory is corrupt.
To answer the first question, you could simply include data.h in energy.cpp.
#include "data.h"
Unfortunately, you've created "part" in the global space and so each .cpp file will independently create it. When it goes to link the object files, it will see that multiple references to "part" exist. What you can do here is use the "extern" keyword and in data.h, you would simply declare it as an external variable. Or, because you only reference "part" in main.cpp, you could just move the global definition in there and the problem is solved.
Now, when it comes to what you have done in energy.cpp, you've create a separate variable also called "part". When scoping rules are applied, it means that the compiler is going to take the local definition over the global definition. Since you are passing a class object and not a class array, you'll get a compiler error when referencing it like "part[0].mass".
Instead, why are you concerned about the value of the other particle and not the particle you passed in? If you want the mass of a particular Particle object, then you should write it like "part.mass"
Of course, I would argue that what you really want to create is a member function for energy within Particle. Right now, you are currently using classes in a C style struct way. This means that you are missing the ability to use all the object oriented goodness that C++ has to offer. You could do it like this
class Particle
{
protected:
double mass;
double charge;
double posx,posy,posz;
public:
void SetMass(double newMass) { mass = newMass; }
void SetCharge(double newCharge) { charge = newCharge; }
void SetX(double newX) { posX = newX; }
void SetY(double newY) { posY = newY; }
void SetZ(double newZ) { posZ = newZ; }
double GetEnergy() { return 2.0; }
};
To answer your second question, C++ assumes you know more about the memory then it does. There is no bounds checking in GCC(AFAIK) because the memory could be allocated anywhere at any time and deallocated as well. However, unlike other languages, you have to manage the memory yourself. There's a lot of optimizations and C++ trickery that this enables(like declaring a zero sized array for unknown sizes and assigning a block of memory to it).
Cheers!
I've been working through Bjarne Stroustrup's "The C++ Programming Language" (2nd edition - I know I should really get a new copy but this is a library book!), and had a few questions about one of his simpler questions. In Chapter 2, when talking about Declarations and Constants, he lists a set of declarations, some of which are definitions as well. In an exercise at the end of the chapter, he challenges the reader to go back and re-write the list, this time changing all of the defined declarations to just declarations and changing all of the non-defined ones to have a definition.
I have completed this task, hopefully mostly correctly, but there were a few parts I got stuck on. I would appreciate it if anyone could take a quick look through my list, check if there are any of the original list I mis-allocated, and then check my changes - including most specifically how to declare but not define a typedef, and if my enum declaration-not-definition is right. Thanks very much to anyone who helps. I apologise since this isn't strictly a direct code question - i.e. there's no compilable code here, it's more... I dunno. But it does have code in it, so I hope that's okay.
// Original:
/*
char ch; // Definition.
int count = 1; // Definition.
char* name = "Njal"; // Definition.
struct complex { float re, im; }; // Definition.
complex cvar; // Definition.
extern complex sqrt(complex); // Declaration, NOT definition.
extern int error_number; // Declaration, NOT definition.
typedef complex point; // Definition.
float real(complex* p) { return p->re; } // Definition.
const double pi = 3.1415926535897932385; // Definition.
struct user; // Declaration, NOT definition.
template<class T> abs(T a) { return a < 0 ? -a : a; } // Definition.
enum beer { Carlsberg, Tuborg, Thor }; // Definition.
*/
// Definitions/Declarations switched:
/*
extern char ch;
extern int count;
extern char* name;
struct complex;
extern complex cvar;
complex sqrt(complex in) { // Yes, my maths may be wrong here. Doing the actual maths from memory.
complex out;
out.re = (in.re * in.re) - (in.im * in.im);
out.im = (in.re * in.im)*2;
return out;
}
int error_number;
// No idea how to declare but not define a typedef!
float real(complex* p);
extern const double pi;
struct user { string name; int age; char gender; }; // Lets assume we include <string>, and yes, using int for age *might* be a bit wasteful, but meh.
template<class T> abs(T a);
extern enum beer; // Not sure if this is right.
*/
typedef complex point; is not a definition in C++, but only in C.
You also cannot, from what I know, provide a non-defining declaration for pi without changing its meaning, because the definition it shows has internal linkage, but if you put extern const double pi; you will give it external linkage (possibly conflicting with other translation units's pi names). Note that linkage rules are complicated
static int a;
extern int a; // valid, 'a' still internal
extern int b;
static int b; // invalid!
const double pi1 = 3.14;
extern const double pi1; // valid, and 'pi1' is internal
extern const double pi2;
const double pi2 = 3.14; // valid, but 'pi2' is now external
You also cannot only declare an enumeration without defining it.
I believe your other solutions are correct.