Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Coming from a Java background, I am used to the concept of making a class A, then creating class B to hold specific static instantiations of class A to use throughout the program. Some example Java code:
public class Color {
public int r;
public int g;
public int b;
public Color(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
}
public class Colors {
public static final Color WHITE = new Color(255, 255, 255);
public static final Color BLACK = new Color(0, 0, 0);
}
I have tried a class Color, with a struct Colors named colors, but I get linker errors as colors is reinstantiated in every file I include it in. What is the best way to do this in C++? Or am I trying to solve the problem in the wrong way?
Assuming that your problem is actually the color thing you presented, this would probably be the easiest way to achieve it:
struct Color
{
int r, g, b;
Color(int r, int g, int b)
{
this->r = r;
this->g = g;
this->b = b;
}
static Color WHITE() { return {255, 255, 255}; }
static Color BLACK() { return {0, 0, 0}; }
};
https://godbolt.org/g/DBrM1C
If you for some reason need to be able to reference the static objects (i.e. there should be exactly one static object instance for every named color), you could declare them in the header (Colors.h) and initialize them in the associated compilation unit (Colors.cpp), but that is somewhat cumbersome and also means your compile time constants cannot be inlined/constant folded etc. by the compiler (without link-time optimization at least). It does protect you from recompilations of files that include Colors.h if the constants change though.
This method would be a (not much better) middle ground where there is still one static object instance per color but you can keep it to the header: https://godbolt.org/g/13krNc
Note however that, despite optimizations, the compiler cannot figure out that bar() should always return 255. Instead, it has to check in every call whether the static constants were initialized already and, if not, initialize them (which requires a lock for thread safety!).
In C++ an include is an actual include. That means, in contrast to Java imports, the code is actually copied.
When you now include your file multiple times, you have multiple occurrences of your code. That is why you need to protect your header code from being copied twice.
Solution 1: Write the following as the first line of your header file:
#pragma once
Solution 2 (more portable and widely recommended):
#ifndef MYHEADERFILENAME_H
#define MYHEADERFILENAME_H
// your header code goes here
#endif /* MYHEADERFILENAME_H */
Some more thoughts about your problem:
Do not use a class for encapsulating constexpr values. This is not necessary in C++. In Java there cannot be something outside a class, but in C++ this is perfectly legal. Just declare your symbol and define it in your source file outside a class. You should declare it in your own namespace, though, to avoid name clashes.
Maybe an enum class aka scoped enumeration comes closer to what you really want.
Related
I have a Display class that uses SDL to write pixels to the screen. I'd like another class (Triangle) to be able to use this already existent class object, so I've been trying to pass the object by address.
It's sort of working, in the sense that it is actually calling the methods. However, I was getting a segmentation fault in the DrawPixel function. After checking gdb and checking what values are in the function, I figured out that the color_buffer array does not exist (note that when DrawPixel is called directly from the display class in main it works fine).
After a little more testing, I determined that window_width, window_height etc are not set in the Triangle's version of the Display object. But they do exist in the original Display object.
So I'm assuming that I am not properly passing in my object, but I'm uncertain how to fix this issue as I thought passing by address would work just fine. How can I pass an already existing/instantiated class to another class?
I've also tried putting color_buffer into public variables in case private was causing it, but that didn't help.
Example:
main.cpp
int main() {
Display display;
Triangle triangle(&display);
// This doesn't work
triangle.DrawTriangle(300, 500, 0xFFFFFF00);
// This does work
display.DrawPixel(300, 500, 0xFFFFFF00);
return 0;
}
triangle.hpp
class Triangle {
private:
Display* display;
public:
DrawTriangle(int x, int y, uint32_t color);
};
triangle.cpp
Triangle::Triangle(Display* display) {
display=display;
}
Triangle::DrawTriangle(int x, int y, uint32_t color) {
display->DrawPixel(x, y, color);
}
display.hpp
class Display {
private:
// SDL Stuff defined here
uint32_t* color_buffer;
int window_width = 1920;
int window_height = 1080;
public:
Display();
DrawPixel(int x, int y, uint32_t color);
};
display.cpp
Display::Display() {
// SDL Stuff declared
color_buffer = new uint32_t[window_width * window_height];
}
Display::DrawPixel(int x, int y, uint32_t color) {
// This is receiving the correct values, but doesn't allow me to access
// any index of color_buffer.
color_buffer[(y * window_width) + x] = color;
}
Triangle::Triangle(Display* display) {
display=display;
}
the display is not the member of your class.Use this->display = display instead
You have to use "this" in Triangle constructor. That should solve the problem.
Triangle(Display* display) {
this->display=display;
}
A couple of things to add to the answers above:
use a different naming convention for member variables - this way it is very easy to avoid typos. _display, m_display, Display_ (Clang style =) )
class members are private by default so if you are following convention where attributes are defined on top, there's no need to add private:
Some prefer references (e.g. Display&), mostly to save typing ->, since if `Display goes out of scope it will have the same hilarious effect as passing a pointer.
static analyzers look down on pointer arithmetic(due to possible out-of-bounds writes).
You can use std::array from header:
static constexpr int WIDTH = 1920;
static constexpr int HEIGHT = 1080;
std::array<uint32_t, WIDTH* HEIGHT> m_color_buffer{};
and then either use m_color_buffer[index] = color (no bounds checking, random memory gets written if you write out of bounds in release and normally an exception in debug), or use m_color_buffer.at(index) - slower but this way you get an exception in release mode, but the compiler may complain about the stack size, as the definition is essentially the same as uint32_t buffer[WIDTH*HEIGHT]. std::vector is a better alternative - it hides buffer allocation, manages memory (no need to delete) at expense of the 2 extra pointers for begin and the end of the vector.
The code example lacked a destructor. Every new should have an accompanying delete hence either add it or just switch to a standard library container to avoid the headache =)
Last but not least - both classes override constructors. Display also manages resources. What happens when you copy Display instances? Move them? It is a bit of a headache and leads to a bit of a boilerplate, but it is best to implement Rule of 5 members and avoid accidental surprises =)
PS. C++ is a beautiful language =)
I'm using a pre-C++11 compiler and I'm trying to "export" a constant, without exposing the classes from which this constant is calculated.
// A.hpp ----------------------
struct A{
...
};
// B.hpp ----------------------
struct B{
...
};
// Manager.hpp ------------------
#include "Manager.hpp"
template <size_t a, size_t b>
struct StaticMax
{
enum { value = a>b ? a : b };
}
class Manager
{
public:
static const size_t OverlayDataSize;
...
};
// manager.cpp ------------------
#include "A.hpp"
#include "B.hpp"
// I want the following constant to be available to anyone
// that includes Manager.hpp, but the classes A and B should not
// be visible to anyone else except class Manager
const size_t Manager::OverlayDataSize = StaticMax<sizeof(A),sizeof(B)>::value;
// otherfile.hpp -------------------
#include "Manager.hpp"
struct OverlayData
{
// shared state goes here
uint8 gameState;
uint8 specificState[Manager::OverlayDataSize];
};
class NvRam
{
void Write(OverlayData& serializedState);
....
}
The above code won't compile and results in:
error: ‘Manager::OverlayDataSize' is not a valid template argument for type ‘unsigned
int’ because it is a non-constant expression
Which is already strange since Manager::OverlaySize most definitely is const and its value is calculated at compile time. But according to this question, if a const declaration and its definition aren't in the same location, then the compiler can't use it as a constant. The error persists even if you use a global variable declared with extern. I could have calculated the maximum size differently by using a union (but then structs A and B aren't allowed to have constructors), but that's not the problem, I still can't export that constant to be available at compile-time without exposing structs A and B to everyone. Of course I can side step the whole issue by making the DataOverlay struct a bit more complicated and using new uint8[Manager::OverlayDataSize]; at runtime and be able to maintain strict seperation. But I'm shooting for this to be done statically at compile time.
So how to "export" a compile-time constant while maintaining strict separation between structs A and B and users of Manager?
Here is a (rather ugly) solution.
The core problem is you only need the size of A and B, which are constants, but you are forced to include the whole definition. The solution would be to manually calculate the size and write it in the required place.
But it is easy to forget to update the value when A and B are modified, so we should somehow automatically do the above job.
To achieve this, you can write a code generator, which generates code like this to a header file:
const size_t OverlayDataSize = /* the calculated size */;
and invoke that program each time you rebuild the whole project. (For example, by writing a Makefile. )
That generator can have A.hpp and B.hpp included, calculate max(sizeof(A), sizeof(B)) and run a printf or something similar to write the generated code. The other source files should only #include the generated source.
Since C++ does not have a module system (which will enable you to hide some internal entities) or a complete metaprogramming facility (which allow us to write some code that generates other code), I can only think of this rather ugly way to achieve this. But anyway, it should work.
My first, immediate problem is with many strange errors that look like this:
In function ZN6BeingC2Ev:
multiple definition of 'area'
first defined here
I am writing a basic pathfinding system and I have two classes:
-Area: Areas describe the 2D grid of walls and open spaces that beings navigate through.
-Graph: Every being capable of pathfinding has its own Graph, and each of those graph objects need to get a part of the layout of the world grid from the currently active Area.
So all Graph objects need to know about *area, which in main() is allocated by the usual area = new Area();
But I can't declare Area *area in main.cpp because Graphs wouldn't be able to see it, and its methods won't be able to read it.
So I tried to declare *area in area.h (shown below). My intention was that because Graph #includes "area.h", area would be known to Graph. This causes my my multiple definitions problem.
I am unsure what exactly the problem is, since I am sure I did not define Area in any way outside of its own header file, and partly because my IDE points me to seemingly unrelated functions when I click the error message for the source of the multiple definition.
So my second question: In the interest of avoiding such an error, is there a better structure that will give Graph knowledge of Area objects and access to their contents?
Below is code which I hope demonstrates my intentions, please let me know if anything necessary has been omitted.
area.h
#ifndef AREA_H_INCLUDED
#define AREA_H_INCLUDED
class Area
{
std::vector<int>wallmap;
...
} *area;
#endif // AREA_H_INCLUDED
graph.h
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#include "area.h"
class Graph
{
...
};
#endif // GRAPH_H_INCLUDED
graph.cpp (The problem is in the switch part)
std::vector<Node*>Graph::RequestPath(int startX, int startY, int destX, int destY);
{
for(std::vector<Node*>::iterator it = nodeGraph.begin(); it != nodeGraph.end(); ++it)
{
(*it)->heuristic = std::abs(destX-startX) + std::abs(destY-startY);
switch(area->wallmap[(*it)->id]) // **I need Graphs to know about the wallmap vector in Area, here for example.**
{
....
}
(*it)->fValue = (*it)->heuristic + (*it)->moveCost;
}
}
main.cpp
#include "area.h"
int main()
{
...
area = new Area();
area->Init();
...
delete area;
...
}
Thanks for your assistance!
As pointed out in a comment by #GManNickG, the problem lies with the use of area as a variable in:
class Area
{
std::vector<int>wallmap;
...
} *area;
Every compilation unit that #includes the .h file will define that variable, which leads to the multiple definition error at link time.
I suggest using a function to get the necessary pointer instead of using a global variable.
class Area
{
std::vector<int>wallmap;
...
};
Area* getArea();
Implement it in the .cpp file that implements the member functions of Area, just to keep related definitions together
Then, you can use the function wherever you were using the global variable.
If you must use a global variable, which I strongly advise against, you can use:
class Area
{
std::vector<int>wallmap;
...
};
extern Area* area;
and make sure that area is defined in the .cpp file that implements the member functions of Area, just to keep related definitions together.
There are several questions on these forums about the inheritance of C++ enums for extending (which is actually the thing without the logic). But what about inheritance just for setting specific values?
Currently, there is something like the following in my code:
//lib_impl.h
enum class X {
a = 13, // these values are
b = 42 // implementation dependent
}
//lib.h
#include "lib_impl.h"
void some_func(X param) {
X x = X::a;
}
I just want to avoid the dependecy of the 'lib' from its implementation. Probably, something other than enums must be used for that. As even in C++11 we have the ability only to declare forward enum name, but not its enumerators:
//lib.h
enum class X { a, b } // this is both declaration and definition, unfortunately
void some_func(X param) {
X x = X::a;
}
//lib_impl.h
#include "lib.h"
enum class X { // redefenition, compilation error
a = 13,
b = 42
}
What is the best compile-time solution for such problems?
--
As it seems to be unimplementable in c++, what is the most common way to resolve such issues? Leave the dependency of the 'lib' from the 'impl' as it is? Probably, 'impl' could be split into two parts, small which will be included before the 'lib.h' and other, bigger, to be included after it. Is it ok or I need to abandon the use of enums in favor of abstract classes?
Expose an enum with nominal values (start with 0, sequential say). Inside your library, remap these values to an internal enum with implementation dependent values (say an array for speed, using the external value as index). Reverse the mapping if you export said enum values to the outside (the reverse mapping will be slower).
I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).