Class Definition Instance Instantiation Question - c++

I have a class imgmanager that allows me to load all my images exactly once, it's quite nice, and while prototyping I had all of my files in one place, so I didn't have to worry about cyclical definitions. However after separating all of my classes I have a problem.
My Header File
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#include "Img.h"
#include <vector>
#include <map>
#include <string>
class imgmanager{
protected:
std::vector<sf::Image*> images;
std::map<std::string,int> positions;
public:
sf::Image* addimg(std::string path); //relative to resources
sf::Image* getimg(std::string path);
int size();
virtual ~imgmanager();
sf::Image* operator[](int);
}imagemgr;
#endif
With the instance created after the } and before the ; my compiler complains at me:
So I ask: What should I do to have a global instance of my imagemgr class? Should I just make a global header file and create an instance? (in this particular case I can just make a global variable in my main.cpp, none of the headers require the instance)

Don't create object instances in headers.
Create your object instance in one source file.
If you need to access it across multiple Translation Units, put this in your header:
extern imgmanager imagemgr; // declaration
This will inform all code that can "see" the header that there exists a so-named object; but it will still only actually be defined in the one source file where you wrote:
imgmanager imagemgr; // definition
(This is analogous to the way in which you declare functions in a header, but define them in precisely one source file:
void f(); // declaration
void f() { ... } // definition
)
The above general advice dutifully imparted, I would now question the rationale of having a class at all if you're only going to use one, single, global instance of it. Either make it a "singleton" class, or use free functions in a namespace instead.

If you require a single global instance, i suggest you make the ImageManager a "Singleton".
I'm unsure what to do for complex types, but for a global declaration of a simple data-type you should declare the variable "extern" in the header, and instantiate it in exactly one module (.cpp file).

Related

Scope of a static variable to several files C++ [duplicate]

Well, I'm learning C++ and never really learned how to do stuff that is not OO.
I'm trying to get a bit more experience coding in C style.
GobalInformation.h
#pragma once
#ifndef GLOBALINFORMATION_H
#define GLOBALINFORMATION_H
#include "MapInformation.h"
namespace gi {
MapInformation mapInf;
};
#endif
I would like to be able to access gi::mapInf from every header and cpp in my project. Right now I'm including globalinformation.h in every header, so I'm getting linker errors with multiple definitions.
How can I work around the problem?
In header file only do
namespace gi {
extern MapInformation mapInf;
};
In CPP file provide the actual definition.
namespace gi {
MapInformation mapInf;
};
It will work as you intend.
If you are using the MapInformation across dynamic link library boundaries you might have to link against the library that includes the definition cpp file. Also on Window you might have to use dllimport/dllexport
Be aware that having globals in multiple compilation units can easily lead to order-of-initialization problems. You may wish to consider replacing each global with a function that returns a reference. In your case, put this in one cpp file and declare it in the header:
namespace gi {
MapInformation& getMapInf()
{
static MapInformation result;
return result;
}
}
Global variables are C, but namespaces are C++. There is a good discussion on using global variables and how they can be replaced by Singleton pattern: Globals and Singletons
And here is a simple sample: CPP/Classes/Singleton
Perhaps a better solution is to create a global object that contains all your global data. Then pass a smart pointer to the classes that actually need to access this shared global data.
Example:
class GlobalData
{
public:
int ticks_;
};
//Other file
class ThatNeedsGlobalData
{
public:
ThatNeedsGlobalData(std::shared_ptr<GlobalData> globalData);
};
This will save you some trouble.
Good luck!
Here are a few things that you need to take care of while trying to use global variables the way you have used.
Ensure that all the header files that the header files that GobalInformation.h includes are also enclosed insides #ifndefs. (I could not see mapinformation.h so I assume you have done it)
Just like CPP, C compiler also does not ensure order of the initialization of variables in different translation units(different C/CPP files).
Hence declare the header file as
//GlobalInformation.h
namespace gi {
extern MapInformation mapInf;
};
In a function that you know would be called first initialize the variable. This way lazy-initialization can also be acheived in C.

avoiding circular inclusion when having to pass back values

what is the best way to handle circular inclusions in the situation where I have a class that communicates with another class, like an API and gets callbacks from that class.
Assume I have a class
.h
class Requestor;
class Api
{
public:
Api();
void Request();
int DoStuff();
private:
Requestor *p_rq_;
};
.cpp
#include "api.h"
#include "requestor.h"
Api::Api()
{
}
void Api::Request() {
this->DoStuff();
}
void Api::ReturnRequestId( int id ) {
this->p_rq->SetLastRequestId( id );
}
and
.h
class Api;
class Requestor
{
public:
Requestor();
void MakeRequest();
void SetLastRequestId( int );
private:
Api api_;
int last_request_id_;
};
.cpp
#include "requestor.h"
#include "api.h"
Requestor::Requestor()
{
}
void Requestor::MakeRequest() {
this->api_.Request();
}
void Requestor::SetLastRequestId( int id ) {
this->last_request_id_ = id;
}
In case requestor sends a request and at some point the api gets an id and wants to pass that back to the requestor, how can I do that without including each others .h file which would lead to circular inclusion?
Assume that I cant simply have the function MakeRequest return the id as I dont want to hold that thread until api gets the id?
I am fairly new to c++ and programming, so I may miss the obvious solution. Since I need to call member functions of each other, it is my understanding that forward declaration does not work here.
Also, Api and Requestor should be separate libraries, so I can't make them one class.
You have two different issues, circular dependency between your classes and multiple inclusion of the same header file.
Multiple inclusion is not caused only by simple circular dependencies, like in your case. The usual way to make sure a header is included once and only once in a source file is to use include guards. Normally a header file looks like this:
#ifndef SOME_UNIQUE_NAME_
#define SOME_UNIQUE_NAME_
... header contents ...
#endif
This ensures that no matter how many times a header gets included in a source file (either directly or indirectly), only the first time its contents are actually included, subsequent inclusions are skipped by the preprocessor due to that macro. The macro name must be unique (for obvious reasons), and it is usually some kind of prefix followed by the header name, e.g. LIBNAME_MODULENAME_REQUESTOR_H_.
A widely used alternative, supported by most modern compilers even if not standard as far as I know, is to use a pragma directive at the beginning of the header:
#pragma once
... header contents
Your other issue is circular dependency between your classes. Here you've already found one way to go around it: your Api class holds a pointer to a Requestor object and not the object itself. This allows you to use a forward declaration in Api.h and not include the full class definition.
The Requestor class however holds an Api object, not just a pointer, so the full Api class definition must be available at the point where the api_ member is declared. So you can't use a forward declaration for the Api class in this case, you must actually include the full definition.
Use
#ifndef __filex__
#define __filex__
At the beginning of each .h and
#endif
At the end.
This way, the .h file is read only once

C++ global pointer shared by different files

So I am trying to make a C++ / OpenGL program (using Visual Studio 2010) that deals with Keyboard Input using a class called Operation. The point is to learn a few things since I'm new to both C++ and OpenGL.
I'm using an array 'bool keysDown[256]' to store which keys are pressed. Likewise I want to make an array of operations 'Operation *keyOps[256]', to operate those keys.
And here comes my problem, most of those keys will have no operation so I want an Operation class that will do absolutely nothing, but I only need one global instance/pointer that different files can use.
Now what I wanted to do, was to somehow create a single instance of this 'no operation' class and make it usable in any files that include this header without needing to declare it in each file. (Something like NULL, only in the shape of an Operation class)
So far my 'solution' was to use a namespace like this,
(operation.h)
#ifndef _OPERATION_H
#define _OPERATION_H
#include <iostream>
#include <GL\glut.h>
namespace operations{
class Operation{
protected:
std::string _name;
public:
Operation(std::string name) : _name(name){}
virtual void operate()=0;
std::string getName(){return _name;}
};
(...)
class OPnop: public Operation{
public:
OPnop(): Operation("No operation"){}
void operate(){}
};
static OPnop OPNOP;
Operation* nop(); //implemented in .cpp > {return &OPNOP;}
(...)
};
#endif
Other files can get a pointer to the OPNOP instance by using the operations::nop() function. I've tested and it works, but I'm not sure this works as intended in the background.
I have been searching for extern and static usage on global variables, but I probably didn't understand it all and I didn't find an answer I could relate to my problem. If I'm not mistaken extern variables have to be declared in other files too while static creates a different variable for each file including it.
So my question is, is there a way to declare/instantiate this 'no operation' so that all the files including this header will have access to the same unique instance directly without having to use a function?
Indeed the static keyword has a different meaning in the namespace context than the class context. I believe what you want to do is declare it as extern in your header, and in the implementation (.cpp) file initialize it once. Take a look at this question.
I did something similar here.
I'm using a Gesture class with a single global instance as gGesture to handle all the user interactions.
// .h file
struct Gesture_{
int fingers;
int taps;
eGestureAction action;
bool continious;
};
typedef struct Gesture_ Gesture;
extern Gesture gGesture;
To answer your question on static vs extern, the extern avoids linker problems by not adding same symbol to all translation units.
Notes:
The code was originally intended to work in a C based project, but I think you'll get the idea.
The Gesture object is intended for Touch based devices.

What kind of bad things would happen if you write the whole class in a single file in C++?

In C# or Java, classes are declared and defined at the same time. In C++, the norm is to do that separately. What if we write the whole class in one , say .cpp, file and include that in files that references to it, what kinds of bad thing technically would happen besides a lengthened compilation process?
If your implementation of MyClass is all in the header file MyClass.h then any file you needed to implement MyClass will be included whenever someone includes MyClass.h.
If you change any part of MyClass.h, even if it's trivial (such as adding a comment or even a space) then all files that include it will have to recompile, even if the interface hasn't changed.
Neither of these matters for toy projects, but as you noted, when you have a program that consists of hundreds (or thousands, etc.) of class files, the added compilation time alone makes it worthwhile to separate out implementation from interface.
For instance, if I have the following:
// MyClass.h
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
private:
// ...
};
It would more ideomatically be written as:
// MyClass.h
class Inventory;
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory);
private:
// ...
};
// MyClass.cc
#include "MyClass.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
MyClass()::MyClass()
{
}
void MyClass()::processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
Notice: Including MyClass.h doesn't mean iostream, iomanip, sstream, string, or Inventory.h have to be parsed. Changing how processInventory works doesn't mean all files using MyClass.h have to be recompiled.
Notice how much easier it can be to figure out how to use MyClass now. Header files serve an important purpose: they show people how to use your class. With the modified MyClass.h it's easy to see the list of functions. If each function is defined in the header, then you can't look at just the list of functions. That makes it harder to figure out how to use the class.
You may break the one definition rule.
If you write this:
class foo
{
public:
void doit();
};
foo::doit() {}
and include that in multiple classes, you will have multiple definitions of foo::doit and your link will fail.
But if you make all your classes inline, either by defining them within the class declaration:
class foo
{
public:
void doit() {
}
};
or by explicitly making them inline:
class foo
{
public:
void doit();
};
inline void foo::doit() {}
then you can include that file as many times as you like.
The linker will see multiple definitions of the class's members when you try to combine multiple such objects. Thus, you won't be able to produce a binary from source files that include anything in more than one place.
Typically you separate the declaration and definition of a class. This allows you to use your class in different source files by simply including the declaration.
If you include a .cpp which has both declaration and definition into 2 different source files then that class will be doubly defined.
Each .cpp that the class is included into will compile fine into object files. However each class must have only 1 definition total or else you will not be able to link your object files together.
The most important thing to understand about #include contrasted with other languages importing methods, is that #include COPIES the contents of that file where the #include directive is placed. So declaring and defining a class in the same file will create three things:
Significantly increase your compile
times.
If your definitions are not inline
you will get linker errors, since
the compiler finds multiple
definitions to the same functions
That would expose the implementation
to the user, instead of only the interface.
That is why it is common practice to define large classes in separate files, and on some ocassions, really small classes with small implementations (like smart pointers) in one file(To also implicitly inline methods).
#Bill
I think it is important to underscore Bill's point:
Notice how much easier it can be to
figure out how to use MyClass now.
Header files serve an important
purpose: they show people how to use
your class.
the .h file being more or less the "public" doc to allow the understanding of how your class works in some ways conceptually--an Interface. Remember the source file should be thought of as proprietary. I remember learning a lot about how Unix worked in my early C/C++ days by reading header files. Also remember that inline function complexities should be no more than accessor's
A big reason for a class to be defined in a cpp-file is that it isn't needed publically, it is just a helper function (like e.g. a functor). Some people seem to be afraid to put the complete class in the cpp-file, while that just shows your intent of only using the class there.
Files are usually the atoms of your version control system - if you partition things sensibly into different files, then it becomes possible for a team of developers to check out only the parts they each need to work on. Put everything in one file and you can't do that.

How can I avoid including class implementation files?

Instead of doing
#include "MyClass.cpp"
I would like to do
#include "MyClass.h"
I've read online that not doing so is considered bad practice.
Separate compilation in a nutshell
First, let's get some quick examples out there:
struct ClassDeclaration; // 'class' / 'struct' mean almost the same thing here
struct ClassDefinition {}; // the only difference is default accessibility
// of bases and members
void function_declaration();
void function_definition() {}
extern int global_object_declaration;
int global_object_definition;
template<class T> // cannot replace this 'class' with 'struct'
struct ClassTemplateDeclaration;
template<class T>
struct ClassTemplateDefinition {};
template<class T>
void function_template_declaration();
template<class T>
void function_template_definition() {}
Translation Unit
A translation unit (TU) is a single source file (should be a **.cpp* file) and all the files it includes, and they include, etc. In other words: the result of preprocessing a single file.
Headers
Include guards are a hack to work around lack of a real module system, making headers into a kind of limited module; to this end, including the same header more than once must not have an adverse affect.
Include guards work by making subsequent #includes no-ops, with the definitions available from the first include. Because of their limited nature, macros which control header options should be consistent throughout a project (oddball headers like <assert.h> cause problems) and all #includes of public headers should be outside of any namespace, class, etc., usually at the top of any file.
See my include guard naming advice, including a short program to generate include guards.
Declarations
Classes, functions, objects, and templates may be declared almost anywhere, may be declared any number of times, and must be declared before referring to them in any way. In a few weird cases, you can declare classes as you use them; won't cover that here.
Definitions
Classes may be defined at most once[1] per TU; this typically happens when you include a header for a particular class. Functions and objects must be defined once in exactly one TU; this typically happens when you implement them in a **.cpp* file. However, inline functions, including implicitly inline functions inside class definitions, may be defined in multiple TUs, but the definitions must be identical.
For practical purposes[2], templates (both class templates and function templates) are defined only in headers, and if you want to use a separate file, then use another header[3].
[1] Because of the at-most-once restriction, headers use include guards to prevent multiple inclusion and thus multiple definition errors.
[2] I won't cover the other possibilities here.
[3] Name it blahblah_detail.hpp, blahblah_private.hpp, or similar if you want to document that it's non-public.
Guidelines
So, while I'm sure everything above is all a big ball of mud so far, it's less than a page on what should take up a few chapters, so use it as a brief reference. Understanding the concepts above, however, is important. Using those, here's a short list of guidelines (but not absolute rules):
Always name headers consistently in a single project, such as **.h* for C and **.hpp* for C++.
Never include a file which is not a header.
Always name implementation files (which are going to be directly compiled) consistently, such as **.c* and **.cpp*.
Use a build system which can compile your source files automatically. make is the canonical example, but there are many alternatives. Keep it simple in simple cases. For example, make can be used its built-in rules and even without a makefile.
Use a build system which can generate header dependencies. Some compilers can generate this with command-line switches, such as -M, so you can make a surprisingly useful system easily.
Build Process
(Here's the tiny bit that answers your question, but you need most of the above in order to get here.)
When you build, the build system will then go through several steps, of which the important ones for this discussion are:
compile each implementation file as a TU, producing an object file (**.o*, **.obj*)
each is compiled independently of the others, which is why each TU needs declarations and definitions
link those files, along with libraries specified, into a single executable
I recommend you learn the rudiments of make, as it is popular, well-understood, and easy to get started with. However, it's an old system with several problems, and you'll want to switch to something else at some point.
Choosing a build system is almost a religious experience, like choosing an editor, except you'll have to work with more people (everyone working on the same project) and will likely be much more constrained by precedent and convention. You can use an IDE which handles the same details for you, but this has no real benefit from using a comprehensive build system instead, and you really should still know what it's doing under the hood.
File Templates
example.hpp
#ifndef EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
#define EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
// all project-specific macros for this project are prefixed "EXAMPLE_"
#include <ostream> // required headers/"modules"/libraries from the
#include <string> // stdlib, this project, and elsewhere
#include <vector>
namespace example { // main namespace for this project
template<class T>
struct TemplateExample { // for practical purposes, just put entire
void f() {} // definition of class and all methods in header
T data;
};
struct FooBar {
FooBar(); // declared
int size() const { return v.size(); } // defined (& implicitly inline)
private:
std::vector<TemplateExample<int> > v;
};
int main(std::vector<std::string> args); // declared
} // example::
#endif
example.cpp
#include "example.hpp" // include the headers "specific to" this implementation
// file first, helps make sure the header includes anything it needs (is
// independent)
#include <algorithm> // anything additional not included by the header
#include <iostream>
namespace example {
FooBar::FooBar() : v(42) {} // define ctor
int main(std::vector<std::string> args) { // define function
using namespace std; // use inside function scope, if desired, is always okay
// but using outside function scope can be problematic
cout << "doing real work now...\n"; // no std:: needed here
return 42;
}
} // example::
main.cpp
#include <iostream>
#include "example.hpp"
int main(int argc, char const** argv) try {
// do any global initialization before real main
return example::main(std::vector<std::string>(argv, argv + argc));
}
catch (std::exception& e) {
std::cerr << "[uncaught exception: " << e.what() << "]\n";
return 1; // or EXIT_FAILURE, etc.
}
catch (...) {
std::cerr << "[unknown uncaught exception]\n";
return 1; // or EXIT_FAILURE, etc.
}
This is called separate compilation model. You include class declarations into each module where they are needed, but define them only once.
In addition to hiding implementation details in cpp files (check other replies), you can additionally hide structure details by class forward declaration.
class FooPrivate;
class Foo
{
public:
// public stuff goes here
private:
FooPrivate *foo_private;
};
The expression class FooPrivate says that FooPrivate is completely defined somewhere else (preferably in the same file where Foo's implementation resides, before Foo's stuff comes. This way you make sure that implementation details of Foo(Private) aren't exposed via the header file.
You needn't include .c or .cpp files - the compiler will compile them regardless whether they're #included in other files or not. However, the code in the .c/.cpp files is useless if the other files are unaware of the classes/methods/functions/global vars/whatever that's contained in them. And that's where headers come into play. In the headers, you only put declarations, such as this one:
//myfile.hpp
class MyClass {
public:
MyClass (void);
void myMethod (void);
static int myStaticVar;
private:
int myPrivateVar;
};
Now, all .c/.cpp files that will #include "myfile.hpp" will be able to create instances of MyClass, operate on myStaticVar and call MyClass::myMethod(), even though there's no actual implementation here! See?
The implementation (the actual code) goes into myfile.cpp, where you tell the compiler what all your stuff does:
//myfile.cpp
int MyClass::myStaticVar = 0;
MyClass::MyClass (void) {
myPrivateVar = 0;
}
void MyClass::myMethod (void) {
myPrivateVar++;
}
You never include this file anywhere, it's absolutely not necessary.
A tip: create a main.hpp (or main.h, if you prefer - makes no difference) file and put all the #includes there. Each .c/.cpp file will then only need to have have this line: #include "main.hpp". This is enough to have access to all classes, methods etc. you declared in your entire project :).
You should not include a source file (.c or .cpp). Instead you should include the corresponding header file(.h) containing the declarations. The source files needs to be compiled separately and linked together to get the final executable.
Cpp files should be defined in your compiler script to be compiled as object files.
What ide are you using?
I am going to assume you are compiling with gcc, so here is the command to compile two .cpp files into one executable
gcc -o myclasses.out myclass.cpp myotherclass.cpp
You should only use #include to include class definitions, not the implentation
One thing you will want to watch out for when including you class declarations from a .h/.hpp is make sure it only ever gets included once. If you don't do this you will get some possibly cryptic compiler errors that will drive you up the wall.
To do this you need to tell the compiler, using a #define, to include the file only if the #define does not already exist.
For example (MyClass.h):
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
// Memebers and methods
}
#endif
// End of file
This will guarantee your class declaration only gets included once even if you have it included in many different .cpp files.