Several times I used the pimple idiom to get a short compilation time. To get a "good" header file I return a pointer of a vector that contains pointer of QPoint (an Qt-object).
Lets have a look at my header file:
#ifndef CHEXAGON_H
#define CHEXAGON_H
class QPoint;
class QVector;
class CHexagon
{
public:
CHexagon(const unsigned int & PosX, const unsigned int & PosY, const unsigned int & Radius);
QVector * getEdges();
QPoint * getCenter();
private:
class Pimple;
Pimple * pPimple;
};
#endif // CHEXAGON_H
Whats wrong with it?
QVector isn't a class, it is a class template and can't be declared as you did.
template <typename T> QVector;
and then using QVector<QPoint*> should do what you want.
Nothing.
What makes you think that something is wrong with it?
Related
I have been attempting to make some code, but I am a bit new to c++ and need some help.
I cannot instantiate class Player as a pointer, because it's an "incomplete type" (or undefined type, vs says both). Below are some (simplified, albeit not very) versions of my code:
Entity.h
#pragma once
#include <vector>
class Entity
{
public:
static void init();
class EntityObject;
class Player;
static std::vector<EntityObject*> entities;
};
Entity.cpp
#include "Entity.h"
void Entity::init()
{
entities = std::vector<EntityObject*>();
}
class Entity::EntityObject
{
private:
float velX, velY, x, y;
public:
EntityObject(float xa, float ya) { x = xa; y = ya; }
float getVelX() { return velX; }
float getVelY() { return velY; }
float getX() { return x; }
float getY() { return y; }
};
class Entity::Player : EntityObject
{
public:
Player(float xa, float ya) : EntityObject(xa, ya)
{
printf("Player created");
}
};
Can anyone tell me why
#include "Entity.h"
int main(int argc, char* argv)
{
Entity::init();
Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Entity::entities.push_back(player);
}
gives an incomplete/undefined type?
Thanks.
Edit:
The errors are:
Both errors direct to this line: Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Error (active) E0070 incomplete type is not allowed
Error C2027 use of undefined type 'Entity::Player'
You defined the Entity::Player class in the .cpp file, not in the .h file. Therefore, even though the main() includes the .h file, it does not know about Entity::Player.
Entity::Player is forward declared in Entity.h.
When the compiler compiles your main.cpp module, it does not know anything about this class except that it exists, in particular it has no idea that this class as a constructor taking two float : Player(float xa, float ya)
=> Your issue is related to forward declaring, not nested class.
Read this thread to understand your problem
What are forward declarations in C++?
Read this one to understand what you can and what you can't do with forward declaration
When can I use a forward declaration?
I'm doing something like this
Class.hpp:
class Class {
private:
static const unsigned int arraySize;
int ar[arraySize+2];
};
Class.cpp:
#include <Class.hpp>
const unsigned int arraySize = 384;
The compiler (q++, a c++ compiler for the QNX OS based on g++) gives me error: array bound is not an integer constant while compiling a unit including Class.hpp (not while compiling Class.cpp).
Why isn't that working? I know that a static const member can be used as an array bound, guaranteed by the C++ standard (see this anwser). But why doesn't the compiler see the result of static const + const as a constant?
This is good code which should have been accepted by the compiler:
class Class {
const static int arraySize = 384;
int ar[arraySize+2];
};
and if it isn't, your compiler is broken.
However, if you move actual constant out of the header file to selected translation unit, that invalidates the code.
// Class.h
class Class {
const static int arraySize;
int ar[arraySize+2]; // ERROR
};
// Class.cpp
const int Class::arraySize = 384;
This is because the size of your Class object cannot be determined at compile time from the data available in the header alone. This is not exactly right reason, but reasoning along these lines helps to understand compilation errors such as this.
To avoid making such mistakes, you can replace static const int with an enum, e.g.
class Class {
enum { arraySize = 384 };
int ar[arraySize+2];
};
I'm surprised this actually compiles on gcc, as a comment says. Since the 384 isn't in the header file, the size of the Class is not known to other compilation units. It might not matter in some compilation units depending on how/if they are using Class, but I can't imagine this compiling:
// this is a source file called, say, blah.cpp
#include <Class.hpp>
void someFunc()
{
void *mem = malloc(sizeof(Class)); // size is not known, so this can't compile
// do something with mem
}
You need to have in your .hpp:
class Class {
private:
static const unsigned int arraySize = 384;
int ar[arraySize+2];
};
.. as it is in the OP that you link to here.
Hey i'm getting this odd error when I leave the namespace sf{ declaration in the later code:
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(70): error C2989: 'sf::Body' : class template has already been declared as a non-class template
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(11): error C3856: 'sf': class is not a class template
The code worked fine when it wasn't a template class for the past 3 weeks, With the same sf::Body class name; i just recently changed it to make it more flexible. Can i not declare a template class inside a namespace or what?
Here's the code:
#include <SFML/Graphics.hpp>
#include <vector>
#include <math.h>
#include <cmath>
namespace sf{ //when i take this out and the closing bracket the code runs fine
template<typename drawable>
class Body : public sf::Drawable{
private:
sf::Vector2f MoveVal;
std::vector<drawable> Drawables;
public:
Body(const Vector2f& Position = Vector2f(0, 0), const Vector2f& Scale = Vector2f(1, 1), float Rotation = 0.f, const Color& Col = Color(255, 255, 255, 255)){
SetPosition(Position);
SetScale(Scale);
SetRotation(Rotation);
SetColor(Col);};
// Overide Drawable Functions To Detect any Movement
void SetX(float X){
MoveVal.x += X - GetPosition().x;
Drawable::SetX(X);};
void SetY(float Y){
MoveVal.y += Y - GetPosition().y;
Drawable::SetY(Y);};
// Regular Functions
void AddObject(drawable& Object){
Object.Move(GetX(),GetY());
Drawables.push_back(Object);};
void DestroyObject(unsigned short Index){
Drawables.erase(Drawables.begin()+Index);};
void Clear(){
Drawables.clear();};
drawable& GetObject(unsigned short index)
{return Drawables[index];};
unsigned int GetNumbObjects()
{return Drawables.size();};
void Draw(sf::RenderTarget& target){
for(unsigned short I=0; I<Drawables.size(); I++){
//Body offset
Drawables[I].SetPosition(
Drawables[I].GetPosition().x + MoveVal.x,
Drawables[I].GetPosition().y + MoveVal.y);
} // TODO: add tint based on overall Body Color
target.Draw(*this);
//Reset all the Change Values
MoveVal.x=0;
MoveVal.y=0;
};
void Render(sf::RenderTarget& target) const{
for(int I=0; I< Drawables.size(); I++)
Drawables[I].Draw(target);
};
};// Body Class
} //namespace sf
Ok found the problem:
In a previously included header file: Shape.hpp I declare Body as a friend with the following syntax:
friend class Body;
Which apparently makes the compiler assume Body is not a template (no template indication is made)
The correct syntax was:
template <typename drawable>
friend class Body;
Because now the compiler understands Body as a template class
The two most likely candidates based on your information are that Graphics.hpp has mismatched { } or that you had a forward declaration of class Body without marking it a template.
sf::Body is a name that seems to be already taken (for a class whereas you're declaring a template). Are you sure you want to put your code in the sf namespace? It's more customary to use one's own namespaces rather than those of the libraries they use.
I am using the rapidxml lib.
It defines a function to parse files in this way:
template<int Flags>
void parse(Ch *text)
The lib provides const int flags for example:
const int parse_declaration_node = 0x20;
So I created a pointer to a static int in my class:
const int * parser_mode;
And in the class constructor I assigned it its value:
parser_mode = &rapidxml::parse_declaration_node;
Then when I try to use this const int * as template argument to the parse function:
tree->parse<parser_mode>(file->data());
I get this error message:
error: ‘GpxSectionData::parser_mode’ cannot appear in a
constant-expression
This rest of the statement seems correct since:
tree->parse<0>(file->data());
doesn't produce compilation error...
Could you please tell me what I am missing here?
Thank you!
Thanks to the explanations below I will probably define it out of the class:
So I think this is:
class Myclass {
static const int parser_mode;
[...]
}
static const int Myclass::parser_mode = rapidxml::parse_declaration_node;
template<int Flags> void parse(Ch *text) ... const int * parser_mode;
Your template takes an int as a template parameter, but you are passing it an int*. The types int and int* are not the same.
Try tree->parse<rapidxml::parse_declaration_node>(file->data());
You cannot use variable for value of template parameter.
Instead you can add Flags template parameter to your class
template<int Flags>
class CClass {
//...
};
And set Flags parameter for class instance
CClass<rapidxml::parse_declaration_node> obj;
#pragma once
#include "LudoCore/Singleton.h"
class LudoTimer : public Singleton<LudoTimer>
{
friend class Singleton<LudoTimer>;
public:
void Update();
void ShortenDay();
void LengthenDay();
UINT64 GetDeltaTime() const;
float GetPercentageOfDayElapsed() const;
private:
LudoTimer();
~LudoTimer();
UINT64 GetTickCount64() const;
UINT64 GetElapsedSeconds() const;
UINT64 m_DeltaTime;
// Tick Count
UINT64 m_CurrFrameTick;
UINT64 m_LastFrameTick;
int m_SecondsInADay;
static const int SHORTEST_POSSIBLE_DAY = 60;
static const int LONGEST_POSSIBLE_DAY = 86400;
static const int CHANGING_INTERVAL = 600;
};
To me, the above code looks normal. However, I'm new to C++ so I may be missing some nuance. I'm getting a bunch of compiler errors from it, such as:
error C2447: '{' : missing function header (old-style formal list?)
and
error C2236: unexpected 'class'
'LudoTimer'. Did you forget a ';'?
What gives!
Have a look in the other header (LudoCore/Singleton.h). The second error implies that the error is before the class LudoTimer declaration at the top.
My guess is that Singleton.h defines a class, and there's a missing ';' after that class definition.
The error is probably in LudoCore/Singleton.h or something else included earlier. Make sure your class definitions have ; semicolons after them and all that.
Quick test: comment out the #include and stick a template<class C> class Singleton; predeclaration there instead. If the compiler now complains about incomplete types, I'm right, and if not, post more details.
Well, the following compiles fine for me, so the error is very likely not in the code you showed us. I suggest you have a second look at Mike's suggestion that there is an error in Singleton.h.
//#include "LudoCore/Singleton.h"
#include <windows.h>
template< typename T >
class Singleton {};
class LudoTimer : public Singleton<LudoTimer>
{
friend class Singleton<LudoTimer>;
public:
void Update();
void ShortenDay();
void LengthenDay();
UINT64 GetDeltaTime() const;
float GetPercentageOfDayElapsed() const;
private:
LudoTimer();
~LudoTimer();
UINT64 GetTickCount64() const;
UINT64 GetElapsedSeconds() const;
UINT64 m_DeltaTime;
// Tick Count
UINT64 m_CurrFrameTick;
UINT64 m_LastFrameTick;
int m_SecondsInADay;
static const int SHORTEST_POSSIBLE_DAY = 60;
static const int LONGEST_POSSIBLE_DAY = 86400;
static const int CHANGING_INTERVAL = 600;
};
I was wondering if LudoTimer is declared at the point that it is used by Singleton and if a forward declaration would help? I didn't need one in VisualStudio 2005 and like sbi I could compile the code by supplying a declaration of Singleton. If I added a simplistic implementation I could even do:
LudoTimer* timer = Singleton<LudoTimer>::instance();
One more thing:
error C2236: unexpected 'class' 'LudoTimer'. Did you forget a ';'?
You could try adding a semicolon on a blank line after the #include to answer this question. If it helps then you can show that there is a problem in the header file without needing to edit it.