#pragma once
#include "Predefined.h"
#include <string>
#include <vector>
using namespace std;
namespace Packets
{
enum { EnumLoginData, EnumPlayerData };
struct LoginData
{
std::string username;
std::string password;
};
struct PlayerData
{
Predefined::Vector2 position;
};
struct MainPacket
{
char type;
int id;
LoginData loginData;
vector<PlayerData> playerData;
};
}
The code above is a single header file called PacketDefines.h. I have a couple of structs prepared as you can see which I will use in another part of my program. Now, the struct PlayerData uses a Predefined::Vector2 object which is a custom struct I created in Predefined.h which is included in the current header file.
The problem is that I get this error on it:
error C2146: syntax error : missing ';' before identifier 'position'
Also, this makes it so that something else in the code, that depends on this struct causes to throw an error:
error C2039: 'position' : is not a member of 'Packets::PlayerData'
This is the Predefined header file:
#pragma once
#include <iostream>
#include <memory>
#include "PacketDefines.h"
// some other includes
using namespace std;
#define LOBBY_MAX_CONNECTIONS 5
#define MAX_DATA_SIZE 512
namespace Predefined
{
struct Vector2
{
Vector2(float valueX = 0.0f, float valueY = 0.0f) : x(valueX), y(valueY) {}
float x;
float y;
};
struct Vector3
{
Vector3(float valueX = 0.0f, float valueY = 0.0f, float valueZ = 0.0f) : x(valueX), y(valueY), z(valueZ) {}
float x;
float y;
float z;
};
struct Connection
{
int ID;
SOCKET socket;
Packets::PlayerData playerData;
};
struct Lobby
{
string lobbyName;
vector<Connection> connectionList;
};
}
I have no idea what is going on since everything is linked like it should as far as I know. I hope my problem is clear and someone can help me solving these errors.
This is a superficial overview, but your "Predefined.h" contains two distinct sections; the first are your Vector classes, the second are more complex classes which contain application logic. To overcome this, you actually need three header files:
Vectors.h -> Should define Vector2 and Vector3, and include none of your application structures
PacketDefines.h -> Should #include "Vectors.h" and nothing else (doesn't need to include Predefined.h).
Connection.h -> Should #include "PacketDefines.h".
Out of scope for this question, I'd also recommend changing your header names to something more meaningful (yes, headers typically declare symbols and define structures; so what?).
Related
I just switched from Python to C++. This is a practice I did for struct. There's always an error 'incomplete type is not allowed' if I don't directly use struct at the source file.
I have review many answers at stack overflow and tried to add typedef in header or remove struct at std::vector<double> timesteps(struct temporal_info time), but none of them work.
Here's my dmdbase.h
#ifndef dmdbase
#define dmdbase
#include <iostream>
#include <vector>
class DMDBase
{
public:
struct temporal_info
{
double t0;
int trend;
double dt;
};
std::vector<double> timesteps(struct temporal_info time);
};
#endif
Here's my dmdbase.cpp
using namespace std;
std::vector<double> timesteps(struct temporal_info time)
{
std::vector<double> time_map;
double final = time.trend + time.dt;
for (double t = time.t0; t < final; t += time.dt)
{
time_map.push_back(t);
}
return time_map;
}
You don't need the struct keyword in the function call site, that is not part of the type
std::vector<double> timesteps(temporal_info time);
Also: Issue is struct 'temporal_info' only defined inside the DMDBase class.
So you have to do this
std::vector<double> DMDBase::timesteps(temporal_info time);
In dmdbase.cpp make sure you specify that timesteps is a method of DMDBase class.
And remove struct keyword before temporal_info as it was already mentioned.
std::vector<double> DMDBase::timesteps(temporal_info time)
{
...
}
The emphasis is on DMDBase::timesteps
try this
#include <iostream>
#include <vector>
typedef struct temporal_info temporal_info;
class DMDBase
{
public:
struct temporal_info
{
double t0;
int trend;
double dt;
};
std::vector<double> timesteps(temporal_info time);
};
I've got multiple classes from multiple engineers which I am using and they have the same named structures in the classes. From this I get the error "'struct' type redefinition". How do I get around this?
Example:
// Eng1Class.h
#pragma once
struct Eng1And2SameName
{
unsigned int bottle;
};
class Eng1Class
{
public:
Eng1Class();
~Eng1Class();
};
.
// Eng2Class.h
#pragma once
struct Eng1And2SameName
{
float x, y;
};
class Eng2Class
{
public:
Eng2Class();
~Eng2Class();
};
.
// Main Program
#include "stdafx.h"
#include "Eng1Class.h"
#include "Eng2Class.h"
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Error: error C2011: 'Eng1And2SameName' : 'struct' type redefinition
According to this Compile error "'struct' type redefinition" although it's the first definition for it the #pragma once should fix the issues, but I still see the error. Any insights you can provide?
No, #pragma once prevents the header files from being included more than once - each is included once -> redefinition.
they have the same named structures in the classes
*header files
The're not defined inside the classes (nested), but they could be:
class Eng1Class
{
public:
struct Eng1And2SameName
{
unsigned int bottle;
};
Eng1Class();
~Eng1Class();
};
Or you could enclose the contents of those headers into two differently named namespaces.
Defining a namespace would help
For example as you said error with same struct definition in same namescope .
Reports error
You can do it by defining namesapce
#include<iostream>
using namespace std;
namespace Eng1 {
struct Eng1And2SameName
{
unsigned int bottle;
};
}
namespace Eng2
{
struct Eng1And2SameName
{
float x, y;
};
}
int main()
{
Eng1::Eng1And2SameName a;
Eng2::Eng1And2SameName b;
return 0;
}
Usually engineers working on the same product are coordinated somehow, at least they will use a common source code repository and a common build. Hence, conflicts should have come up earlier.
"uncoordinated" engineers may happen when they work on different products, and if so, each product could have its own namespace. Thereby, you can combine the products without having conflicts:
// in a header:
namespace Eng1Class {
struct Eng1And2SameName
{
unsigned int bottle;
};
class EngClass
{
public:
EngClass();
~EngClass();
};
}
// in the cpp-file
Eng1Class::EngClass::EngClass() {
cout << "hello, Class 1";
}
// in another (or even the same) header
namespace Eng2Class {
struct Eng1And2SameName
{
float x, y;
};
class EngClass
{
public:
EngClass();
~EngClass();
};
}
// in another (or even the same) cpp-file
Eng2Class::EngClass::EngClass() {
cout << "hello, Class 2";
}
I have a weightedDirectedGraph class and a vertex class in their own header file, weightedDirectedGraph.h. This is it:
#ifndef GRAPH
#define GRAPH
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include "minHeapVertex.h"
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
#endif
And I have a minHeapVertex class in a minHeapVertex.h file that will be used as a priority queue in Dijkstra's algorithm. This is the file:
#ifndef MIN_HEAP_VERTEX
#define MIN_HEAP_VERTEX
#include <iostream>
#include <vector>
#include "weightedDirectedGraph.h"
using namespace std;
class minHeapVertex
{
public:
explicit minHeapVertex(int capacity = 100)
:heapArray(capacity + 1), currentSize{ 0 } {}
bool isEmpty() const
{
return (currentSize == 0);
}
vertex * getMinVertex() const; //getting C2143 error here that says I'm missing a semi-colon before '*'. Doesn't make sense though.
void insert(vertex * insertItem);
void deleteMin();
vertex * deleteAndReturnMin();
void makeEmpty()
{
currentSize = 0;
}
void decreaseKey(int index, int decreaseValue);
void remove(int index);
private:
void buildHeap();
void percolateDown(int hole);
vector<vertex *> heapArray;
int currentSize;
};
#endif
I"m getting a lot of compiling errors (with the first one being a C2143 error on the getMinVertex() declaration) and I think it may have something do with trying to access the vertex class in minHeapVertex.h. Can someone show me what I'm doing wrong? Been at it for hours, tried forward declaring the vertex class, tried removing some of the includes "", looked up the error codes and changed things, but nothing is working and just end up with a bunch of errors.
Problem:
OP has a circular dependency between minHeapVertex.h and weightedDirectedGraph.h.
Solution:
Eliminate the dependency.
minHeapVertex.h defines minHeapVertex. minHeapVertex requires vertex.
weightedDirectedGraph.h defines vertex and weightedDirectedGraph. Neither require minHeapVertex.
Three possibilities at this point:
Spin vertex off into its own vertex.h header. minHeapVertex.h and weightedDirectedGraph.h both include vertex.h and not each other.
weightedDirectedGraph.h does not require minHeapVertex.h, so remove #include "minHeapVertex.h" from weightedDirectedGraph.h to break the circle.
forward definition of class vertex; in minHeapVertex.h and the removal of #include "weightedDirectedGraph.h" from minHeapVertex.h.
Solution 1 is preferred. Giving vertex its own header may prevent future problems. 2 is easiest to implement. 3 is pretty stupid and not recommended.
Why circular dependency prevented minHeapVertex from seeing vertex:
To make this easier to see, I've removed all of the other includes from the header files.
Here's my idiotic little test.cpp
#include "weightedDirectedGraph.h"
int main(int argc, char * argsv[])
{
return 0;
}
The compiler will make a little temp file of test.cpp. It will then start parsing until it finds an include directive. The included file is copy-pasted into the temp file at the include statement. So the temp file looks sort of like this:
#define GRAPH
#include "minHeapVertex.h"
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
int main(int argc, char * argsv[])
{
return 0;
}
The compiler parses down a little further and sees the include of minHeapVertex.h and copy-pastes so you get this:
#define GRAPH
#define MIN_HEAP_VERTEX
#include "weightedDirectedGraph.h"
using namespace std;
class minHeapVertex
{
public:
explicit minHeapVertex(int capacity = 100)
:heapArray(capacity + 1), currentSize{ 0 } {}
bool isEmpty() const
{
return (currentSize == 0);
}
vertex * getMinVertex() const; //getting C2143 error here that says I'm missing a semi-colon before '*'. Doesn't make sense though.
void insert(vertex * insertItem);
void deleteMin();
vertex * deleteAndReturnMin();
void makeEmpty()
{
currentSize = 0;
}
void decreaseKey(int index, int decreaseValue);
void remove(int index);
private:
void buildHeap();
void percolateDown(int hole);
vector<vertex *> heapArray;
int currentSize;
};
using namespace std;
class vertex
{
public:
string data;
list<vertex *> neighbors;
bool known;
int distance, id;
vertex * path;
vertex(string x)
{
data = x;
}
};
class weightedDirectedGraph
{
private:
list<vertex *> vertexList;
vector<vector<int> > edgeWeights; //2D vector to store edge weights
int idCount;
weightedDirectedGraph()
{
idCount = 0;
}
vertex * findVertex(string s);
void dijkstrasAlg(vertex * s);
public:
void addVertex(string x);
//adds bi-directional edges
void addWeightedEdge(string x, string y, int weight);
};
int main(int argc, char * argsv[])
{
return 0;
}
That gets parsed down to #include "weightedDirectedGraph.h", but fortunately GRAPH has been defined, so most of weightedDirectedGraph.h gets left out. If it hadn't, Everything in weightedDirectedGraph.h would have been defined again and minHeapVertex.h would once again been included over and over and eventually the compiler would crash or tell you to expletive deleted off with a politely worded error message.
Anyway, we can already see what's gone wrong in the above code trace: minHeapVertex needs to know type vertex, but that won't be defined for another 20 lines or so.
If test.cpp had been written as
#include "minHeapVertex.h"
int main(int argc, char * argsv[])
{
return 0;
}
The header files would have been included in the other order and it would have compiled, giving a false sense of security until one day you wrote a program that included weightedDirectedGraph.h first. In other words, the library works until it doesn't, and you didn't change a line of the library's code. Have fun pulling your hair out.
Avoid circular dependencies, circular references and circular saws. All three can rip you up pretty bad.
On to using namespace std; This evil little shortcut takes EVERYTHING in the std namespace and adds it to the global namespace. If you had a function named reverse, now you have to deal with potential overload conflicts with std::reverse. The standard library is huge. There are a huge number of function, class, and variable names that are just itching to overload, override and just plain trample your stuff.
But that's your problem.
Putting using namespace std; in a header make it everyone's problem. Anyone who uses your graphing library has to wade through a minefield, and unless they take a close look at your header file and see that declaration they won't have the slightest clue.
Longer discussion can be found here. Either explicitly namespace everything (std::vector, std::string, ...) or pull in only the pieces you need and know will not conflict with your code with using. Eg:
using std::vector;
using std::string;
Do not put this in your header or someone may wind up wonder why their homebrew vector is freaking out. Probably shouldn't be homebrewing vectors, but you can't save everybody.
So I am trying to forward declare a class in my C++ project and then create it in main.
So I have player_obj.cpp which contains the class, classes.h which forward declares the class, and main.cpp which uses it.
classes.h
#ifndef CLASSES_H
#define CLASSES_H
class player_class
{
public:
int x;
int y;
char sprite;
int xprevious;
int yprevious;
private:
bool active;
public:
void update_xy();
player_class(int _x, int _y, char _sprite);
void step();
void destroy();
};
#endif
main.cpp
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
player_class player_obj (5,5,'#');
cout << player_obj.x << ", " << player_obj.y << endl;
return 0;
}
and player_obj.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
class player_class
{
public:
//Coordinates
int x;
int y;
//Sprite
char sprite;
//Previous coordinates
int xprevious;
int yprevious;
//Not everyone can set the activity
private:
//Active
bool active;
//Update xprevious and yprevious - Called by the step event
void update_xy()
{
xprevious = x;
yprevious = y;
}
//All functions public
public:
//Create event/Constructer
player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
//Step event
void step()
{
//Update old xprevious and yprevious
update_xy();
//Do other stuff here
}
//Drestroy event
void destroy()
{
active = false;
}
};
I thought that would work out all right but when I compile and run it I get:
main.cpp:(.text+0x2c): undefined reference to`player_class::player_class(int, int, char)'
I've done some research, but I can't seem to fix this issue.
I greatly appreciate any help!
Well you're sort of close, what you have in your header is indeed a class declaration (not a forward declaration mind you).
The problem is you never defined it. What you have in player_obj.cpp is an abomination of class redefinition, but you already have your class declared. Just include the header file and define the functions one by one and you're done!
#include "classes.h"
player_class::player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
// and so on
If you're serious about learning modern C++ though, a few notes:
#pragma once is the modern way of guarding header files. Don't use those #ifdef..#endif constructs.
generally speaking, don't name anything starting with underscores. Especially not parameters visible as part of your public contract.
you have class initializers for a reason, use them! You don't need half a screen of copy pasting variables in your constructors.
You dont want a forward declaration. You want a declaration. It is a classical case of declaring a class in a header file and defining its functions in a cpp file. Then including the header where-ever you want to use your class
You only need forward declarations when you want to use a pointer to that class as a parameter to a function or a member variable somewhere but the definition of that class is not available yet.
Note that when you forward declare a class, you cannot use this class's member variables or functions in that header
-regards
Gautam
I am trying to do something like this..I have 3 header files
1. coordinates.h
typedef struct {
float x;
float y;
float z;
}coordinates3D;
2.plane.h
#include "coordinates.h"
typedef struct{
coordinates3D plane;
} plane3D;
3.pointArray.h
#include "plane.h"
plane3D points[] ={
{1.0f,3.74f,0.2354f},
{6.823f,9.234f,1.097f},
};
and a cpp file
4. main.cpp
#include "pointArray.h"
int main(int argc, char **argv)
{
std::cout<<points[1].plane.x;
std::cout<<points[0].plane.y;
}
Everything is working fine but I get a warning message
warning: missing braces around initializer for 'coordinates3D'
[-Wmissing-braces]
I am not sure how to solve this warning ...
It's because of the nested structures. Simply add a couple of braces around the values:
plane3D points[] ={
{ { 1.0f,3.74f,0.2354f } },
{ { 6.823f,9.234f,1.097f } },
};
The outermost is for the array, the next pair is for the plane3D structure, and the next is for the coordinates3D structure.