I have a struct Tree that is defined inside Class Parser. I have methods defined in Parser that take Tree as input.
void Parser::InputTree(const Tree& input) {
//uses data from Tree
}
Everything seemed to be working fine. But then I needed to use Tree outside the class. So I decided to define struct Tree in a separate header. I included this header in the header file for Parser. While I see no errors in the header file of Parser, the source file shows errors on my Eclipse. Says member declaration not found pointing to method InputTree.
My question is, first off is this the right strategy to define a struct in a separate header? Second, what am I doing wrong? Third, I have some enum types also that I want to use across classes. Where do I define it?
Right structure:
parser.h
#ifndef _PARSER_H_
#define _PARSER_H_
#include "tree.h"
class Parser {
void InputTree(const Tree& input);
};
#endif /*_PARSER_H_*/
parser.cpp
#include "parser.h"
void Parser::InputTree(const Tree& input){
// use data from Tree
}
tree.h
#ifndef _TREE_H_
#define _TREE_H_
struct Tree {
//nodes
};
#endif /*_TREE_H_*/
Including parser.h includes tree.h and hence, struct Tree is available in the main compilation unit.
A simple rule of the thumb I usually follow, is if a custom datatype (i.e. struct, enum, etc.) is used only within a class, I end up defining this datatype within the definition of the class.
But if the same type is required to be used across 2 or more classes (without any parent-child relationship), I end up defining the type either within another header file and usually within a namespace (when the types or related in some fashion).
And yes you could use multiple such namespaces within multiple header files (to group related types), if you feel the need to distinguish them, but I've just show a simpler example using a single namespace:
/* MyNamespace.h */
#ifndef MY_NAMESPACE_H
#define MY_NAMESPACE_H
namespace MyNamespace {
struct Tree {
int a;
char b;
};
enum SomeEnum {
VALUE_0 = 0,
VALUE_1 = 1,
VALUE_2 = 2
};
}
#endif
/* Parser.h */
#ifndef PARSER_H
#define PARSER_H
#include "MyNamespace.h"
class Parser
{
public:
void InputTree(const MyNamespace::Tree& input);
};
#endif
/* Parser.cpp */
#include "Parser.h"
void Parser::InputTree(const MyNamespace::Tree& input)
{
}
Yes, it is a correct strategy to define the struct in a separate header file.
What you are doing wrong is hard to say without more input - but it probably has to do with includes, include-guards or namespace mismatches.
And finally, you should declare the enums in another header file, with proper include guards.
Related
I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.
I'm trying to create a library for a school work, and I've been wondering if it is safe to declare a templated class on the main header file containing the class definition and method declarations, but then separating the method definitions in a different header file?
Because I have been able to do this in my example below, but I don't know if it will cause me some problems in the long run.
main program
// main.cpp
#include <iostream>
#include "declaration.hpp"
int main()
{
card<int> a(5);
std::cout<<a.getID()<<'\n';
return 0;
}
main header file
in this header file, only the class definition and the declaration of the method getID() is written but not it's definition, and by the end of the class I included the other header file that contains the method definitions.
// declaration.hpp
#ifndef DEC_HPP
#define DEC_HPP
#include <iostream>
template<typename T>
class card
{
public:
T id;
card(const int id) : id(id) {}
T getID();
};
#include "definition.hpp"
#endif
method definitions
This header file contains the method definition of getID() from the main header.
I also included the "declaration.hpp" in this header, and this is the part where I'm not so sure of, because I included both files together with each other.
// definitions.hpp
#ifndef DEF_HPP
#define DEF_HPP
#include <iostream>
#include "declaration.hpp"
template<typename T>
T card<T>::getID()
{
return id;
}
#endif
I have compiled this program and it's working on my machine, but I just wanted to know if this way of isolating my code will cause me some errors in the future, I don't want to put my templated class definitions in a cpp files because I find it hard to maintain.
This is indeed a better approach because it makes your code look simple and better. Moreover, it is the main reason why header file is used.
Your main header file will simply tell that what functions/classes are you using and without even viewing your code, anyone can guess if you are working correctly or not.
There wont be any safety issues at all.
I'm currently writing a simple game with a 2D library and as C++ is a new language to me and as Java is my first fluent programming language, perhaps some bad habits are flowing through to this language that I don't fully understand. I have never had problems doing this in Java but in C++ it causes a ton of errors. As I don't want everything crammed into one class/header file, I've decided to split them up into packages and different classes, but I can't seem to do this without includng the same header files in different places. Here's an example.
Project.h
#ifndef PROJECT_H
#define PROJECT_H
#include "UIManager.h"//this is causing the error, when this, and the class instance is removed the program compiles and runs fine without error
using namespace gamelib;
class Project : public Game {
public:
Project(int argc, char* argv[]);
~Project();
void Update(int elapsed);
void Draw(int elapsed);
void Load();
/*Background*/
Texture * background;
Rectangle* backgroundRectangle;
UIManager ui;
};
#endif
UIManager.cpp
#include "UIManager.h"
void UIManager::load() {
startMenuBackground = new Texture();
startMenuBackground->Load("Sprites/Interface/Transparency.png", false);
startMenuRectangle = new Rectangle(0.0f, 0.0f, Graphics::GetWidth() / 2, Graphics::GetHeight() / 2);
}
UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H
#include "Project.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif
Now I need all of these includes so I can store the necessary textures, and the Texture and Rectangle come from the API that is being used as a namespace in Project.h
I also need a class instance in Project.h, UIManager ui; So i can use this in the Project.cpp file to call methods
How can I get around this without getting all these errors?
If I understand your problem correctly, you want to avoid including header files multiple times. In that case, what you should do is using Include guards. Which makes sure that the header is included once. Optionally you can use #pragma once at the top of your file but that's another discussion.
Example:
#ifndef UIMANAGER_H // you may choose another name than "UIMANAGER_H"
#define UIMANAGER_H
// Your header file code and includes here.
// Do this for your header files.
#endif
Now, do the same for the other header file but instead naming the macro PROJECT_H or similar.
A good practice is to add in the beginning and in the end of the .h files:
#ifndef FILENAME_H
#define FILENAME_H
//Your code here
#endif
Where FILENAME_H is unique for each .h file.
Those are compiler predirectives, which are not included in the executable, but changes the way that the compiler acts.
Adding those, the compiler won't add the same file twice for the same file. If it's already loaded, it won't load it.
Take in account than in C++, header files are parsed independently on each file of the project.
Typically, the fix would be to change your code to this...
#ifndef UIManager_H
#define UIManager_H
// It's pretty normal to put each class in its own header file.
#include "Texture.h"
#include "Rectangle.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
Since you never instantiate either object though, you don't strictly need a full header.
#ifndef UIManager_H
#define UIManager_H
// Since we only use pointers to the classes, we can forward declare the classes
class Texture;
class Rectangle;
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
You can use the macros #ifndef and #define. This is a common pattern. For example, in your UIManager.h file, have the following:
#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__
#include "Project.h"
//Rest of UIManager class definition
#endif
In you Project.h file, have the following:
#ifndef __PROJECT_H__
#define __PROJECT_H__
#include "UIManager.h"
//Rest of Project class definition
#endif
This allows the compiler to compile without errors when it sees circular includes. But it's more preferable to use class forward declaration if possible, but this is a completely different topic.
The macro names __UI_MANAGER_H__ and __PROJECT_H__ are purely randomly chosen. You can choose to use a different naming convention.
I'm writing something in C++. I have 2 classes which I want to contain one into the other as in the folowing (these are just the header files):
//Timing.h
#ifndef _Timing_h
#define _Timing_h
#include "Agent.h"
class Timing{
private:
typedef struct Message{
Agent* _agent; //i get here a compilation problem
double _id;
} Message;
typedef struct MessageArr{
} MessageArr;
public:
Timing();
~Timing();
};
#endif
//Agent.h
#ifndef _Agent_h
#define _Agent_h
#include <string>
#include "Timing.h"
using namespace std;
class Agent{
public:
Agent(string agentName);
void SetNextAgent(Agent* nextAgent);
Agent* GetNextAgent();
void SendMessage(Agent* toAgent, double id);
void RecieveMessage(double val);
~Agent();
private:
string _agentName;
double _pID;
double _mID;
Agent* _nextAgent;
};
#endif
The compilation error is in the Timing.h file inside the definition of the struct:
expected ';' before '*' token
What am I doing wrong?
Try not to include "Agent.h" in Timing.h but include a forward reference instead:
#ifndef _Timing_h
#define _Timing_h
class Agent;
class Timing{
private:
typedef struct Message{
Agent* _agent; //I get here a compilation problem
double _id;
}Message;
typedef struct MessageArr{
}MessageArr;
public:
Timing();
~Timing();
};
#endif
You can include Agent.h in the timing.cpp file.
This way you remove the circular reference and you reduce the coupling between the classes.
Since you don't use the class Timing in your class Agent, you can remove this include as well (but this might be a copy mistake from your shortened example).
Basically - whenever you need either the size of an object or some of it's functionality, you must include its header file. If you don't need it (e.g. if you use only pointers to this object or references), you should not. This reduces compile time (especially for large projects)
For the 1 instance problem - check your favorite design patterns book (e.g. the GoF). The singleton pattern might be what you need.
Rule of thumb.
Do not include other header files from your header files if you don't need to.
Pre-Compiled header file stuff being a notable exception.
If your class only depends on a pointer or a reference you do not need the header file:
Use forward declaration in this situation.
In the source file include only the header files you need to make it work
Include them from most specific to least specific.
This will prevent the problem of hiding a dependency.
Other notes:
Do not use Underscore followed by a capitol letter.
This is reserved for the implementation. see
As in #define _Timing_h
Also note it is traditional that macros are all upper case.
Do not put using namespace X; in a header file
If you do this you pollute the namespace for everybody that uses your header file.
This is a real easy way to PO other developers who now have to re-factor their code to make sure it does not use any of a bunch of new classes/functions/templates that are suddenly being resolved against that was not there before.
So try this:
Timing.h
#ifndef TIMING_H
#define TIMING_H
class Agent;
class Timing{
// STUFF
};
#endif
Agent.h
#ifndef AGENT_H
#define AGENT_H
#include <string>
class Agent{
// STUFF
};
#endif
Timing.cpp
#include "Timing.h"
#include "Agent.h"
// STUFF
Agent.h
#include "Agent.h"
using std::string; // Bring as little as possable into the the global namespace.
// prefer to prefix all cases with std::
// STUFF.
You can't have circular includes.
Stop including "Timing.h" from "Agent.h", since it's not needed there.
Also, you don't need to have the "Agent.h" included in "Timing.h" either, just use a forward reference:
class Agent;
This makes it possible to have pointers to something called Agent.
You need to add the forward declaration of Agent in Timing.h
// Timing.h
#ifndef _Timing_h
#define _Timing_h
class Agent; // fwd declaration.
class Timing{
private:
typedef struct Message{
Agent* _agent; // without fwd decln Agent type is unknown here.
// rest all same.
EDIT:
As suggested by others, you should not be including Agent.h in Timing.h
I'm asking about the best practice widely used in C++ projects. I need to have my own types in the project. It's a collection of couple of typedefs.
Is including header file containing the types good practice in C++ or is it better to use namespaces. If so, why? What are the pros and cons of the two ways?
Right now it looks like this:
types.h:
#ifndef TYPES_H
#define TYPES_H
#include <list>
// forward declaration
class Class;
typedef int TInt;
// ...
typedef std::list<Class> class_list;
#endif
class.h:
#ifndef CLASS_H
#define CLASS_H
#include "types.h"
class Class
{
public:
// ...
TInt getMethod();
private:
// ...
};
How would it look like with namespaces?
The two concepts are orthogonal; comparing them the way you ask makes no sense.
Unless you only use these types in a single file, you have to place them in a header so you can easily bring in their definitions when you need them. Then, within that header, you can include your namespace:
#ifndef TYPES_H
#define TYPES_H
#include <list>
namespace MyNamespace {
// forward declaration
class Class;
typedef int TInt;
// ...
typedef std::list<Class> class_list;
}
#endif
Then later you can do, for instance, MyNamespace::TInt rather than int after you #include "Types.h"
From a dependency point of view, naming all types in a single header is likely to be a maintenance nightmare. It's understandable for the typedef because you want a unique definition, but there is no reason to forward declare the class here.
// types.h
namespace myproject
{
typedef int TInt;
} // namespace myproject
There is no point in forward declaring the Class symbol: you pollute your own namespace. Let each file decide independently if they need the symbol or not and forward declare it on their own.
It's not pretty to declare ClassList either: it should only be available to those who need it. You could create a specific header for forward declaration of Class related stuff:
// class_fwd.h
namespace myproject
{
class Class;
typedef std::list<Class> ClassList;
} // namespace myproject
// class.h
#include "myproject/class_fwd.h"
namespace myproject
{
class Class {};
} // namespace myproject
Erm ... I think including the header file is fine. I'm not sure how namespaces attack this same problem at all ...
The main thing with any "best practice" like this is BE CONSISTENT.