c++ how to create classes that are interdependent - c++

I have a storage class. members of this class are often modified.
each time a member is modified, I'd like to save the state of the class (clone class instance and save it).
So I'd like to create a new class, that will save these states.
For Example:
Say I have a Storage class in file storage.h
class Storage
{
public:
Int m_cnt;
<lots of other members...>
StorageHistory m_his;
};
and a StorageHistory class in file storagehistory.h
class StorageHistory
{
public:
std::vector<Storage> m_history_vec;
};
Assumptions:
StorageHistory class should be kept in Storage class. the reason for that is that Storage class is a main class that can be accessed in all classes/packages. to minimize the changes in the code, I'd like StorageHistory to be coupled with Storage class.
StorageHistory cannot be static or singleton since multiple instance of Storage are created.
Problems:
Cannot compile this code. storage.h needs to be compiled before storagehistory.h and vice versa
If StorageHistory cannot be stored in Storage class then were do I keep it? who is the owner of this class?
Need help to define the connection between these two classed?

First of all: don't make data members public, unless you define a pure data structure. Then: Int is no C++ type.
Now to your questions: you can use forward declarations. Since StorageHistory is used directly in Storage, it cannot be forward declared, but Storage is only used in a template data member (namely a std::vector) in StorageHistory, and that template does not need the definition of Storage if it's only declared as a variable. You need the definition only when you use methods of vector.
So here's the untangled code:
StorageHistory.h
#include <vector>
class Storage;
class StorageHistory
{
std::vector<Storage> m_history_vec;
public:
/* method declarations */
};
Storage.h
#include "StorageHistory.h"
class Storage
{
int m_cnt;
/* <lots of other members...> */
StorageHistory m_his;
public:
/* method declarations */
};
Storage.cpp
#include "Storage.h"
#include "StorageHistory.h" //not necessarily needed, because implicitly included, but thats a matter of coding style
/* ... Storage methods definitions ... */
void Storage::changeVar(/*...*/)
{
m_his.push_back(*this);
/* ... */
}
StorageHistory.cpp
#include "StorageHistory.h"
#include "Storage.h"
/* ... StorageHistory method definitions ... */

Add to your header files
Storage.h
class Storage; //to declear the class before the include
#include "StorageHistory.h"
//continue with the old declearation
class Storage{
....
}
and
StorageHistory.h
class StorageHistory; //to declear the class before the include
#include "Storage.h"
//continue with the old declearation
class StorageHistory{
....
}
remember to have include guards first in the files.
This can be done for all classes to avoid this kind of problem in the future.

You're essentially doing memento design pattern. Your current compilation problems will go away with forward declaration. But for better design and implementation you can see this and this.

You need to use forward declarations for your solution to work. The easiest way is to put these classes in the same header file (but it may be solved a little bit differently):
class StorageHistory; // *** Forward declaration ***
class Storage
{
public:
Int m_cnt;
<lots of other members...>
StorageHistory m_his;
};
class StorageHistory
{
public:
std::vector<Storage> m_history_vec;
};
I don't like your solution, though. The m_his will contain a list of Storage classes and all of them will contain a list of Storage classes (empty, though).
I'd create a singleton with a map of vectors of Storages and wrap a Storage with container containing an UID.
class StorageContainer
{
private:
static int nextUID = 0;
int uid;
Storage data;
public:
StorageContainer()
{
uid = nextUID++; // Watch out for concurrency problems
}
Storage & GetData()
{
return data;
}
};
You could then access a history of a Storage by its UID.
class StorageHistory
{
// The usual singleton stuff
private:
std::unordered_map<int, std::vector<Storage>> history;
public:
std::vector<Storage> & operator[] (int uid)
{
auto iter = history.find(uid);
if (iter == unordered_map::end)
{
std::vector<Storage> newHistory;
history[uid] = newHistory;
}
return history[uid];
}
};

Related

How to declare a class member that may be one of two classes

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

How to access out-of-scope class?

First of all, I would like to apologize if I used incorrect terminology in the question. I do not have any sort of formal training in programming. It was the best I could do to convey the problem.
My question is this:
In the following code structure, how can the Inventory class have complete access to Items vector inside the Player class WITHOUT making the vector static?
-- main.cpp
#include <iostream>
#include <vector>
#include "World.hpp"
#include "Interface.hpp"
int main()
{
World objWorld;
Interface objInterface;
return 0;
}
-- World.hpp
#pragma once
#include "Player.hpp"
class World
{
public:
Player objPlayer;
};
-- Player.hpp
#pragma once
class Player
{
public:
std::vector<int> Items;
};
-- Interface.hpp
#pragma once
#include "Inventory.hpp"
class Interface
{
public:
Inventory objInventory;
};
-- Inventory.hpp
#pragma once
class Inventory
{
public:
// Needs to have complete access to Items, be able to see and modify the vector
};
This is not a C++ question, this is Object Oriented Programming question.
There are many ways to do this. But all of them involve more than one object working together. Either the Player has to have a reference (pointer) to Inventory, or the Inventory has to have a reference to player - somehow.
Here are some options:
You can pass a pointer in constructor (this is just a quick example, please use shared pointers)
class Inventory
{
private:
Player *owner;
public:
Inventory(Player *owner) : owner(owner){}
};
Pass it as method argument
class Inventory
{
public:
void drawFor(Player *owner);
};
Set a field value.
class Inventory
{
private:
Player *owner;
public:
void setOwner(Player *owner) {this->owner = owner;}
};
As a side note, are you sure that Player has vector of items? I would venture that Player may OWN an Inventory. Inventory is more than just a vector of items. It has (potentially complex) limitations on number of items, it can maintain weight of items that affects player's movement, it can be expanded by adding containers. All of it can be useful to Player or NPC. You just have to come up with a good interface for Inventory
There are several issues which you have to consider.
access rights. From outside a class (i.e. from any code other than the class's member functions etc) only public members are accessible, except for friends, which have full access.
visibility. In order to use a member, you must see its declaration.
Thus, you should
// Inventory.hpp
#pragma once
#include "World.hpp" // makes class World visible
class Inventory
{
World& objWorld; // reference to 'my' world object
public:
Inventory(World& w) : objWorld(w) {}
void foo()
{
std::sort(objWorld.objPlayer.Items.begin(),
objWorld.objPlayer.Items.end());
}
};
Of course, you must adapt the rest of your code accordingly:
// Interface.hpp
#pragma once
#include "Inventory.hpp"
class Interface
{
Inventory objInventory;
public:
Interface(World& w) : objInventory(w) {}
};
and
// main.cpp
#include "Interface.hpp"
int main()
{
World objWorld;
Interface objInterface(objWorld);
return 0;
}
Class members can be accessed using the member access operator . (period character). The left hand side is (an expression that yields) an instance of the class, and the right hand side is the name of the member.
Let p be an instance of Player. The expression p.Items will yield the vector of that instance. The class has to be defined, before its members can be accessed.

Hiding private members of c++ library

I have written a library (doesn't matter what it does), which obviously has its header file. Now, I want to hide private elements of that header file, so if I provide my library to somebody, he/she should only see public members (preferably no class definition, nothing other than function definitions). One way would be creating C-style header, which will contain some kind of "init" method which will be used to create an instance of the actual class of library and the user will have to pass a pointer of that object to every function to do the job.
Is it a good practice?
Are there any other publicly accepted ways of doing something like that?
Thanks in advance.
In addition to the Factory pattern (which, in my opinion, can become unwieldy), you can also hide your private members behind a PIMPL (Pointer to IMPLementation):
// Interface.hpp
class Implementation;
class Interface {
public:
Interface() : pimpl(new Implementation()) {}
void publicMethod();
private:
std::unique_ptr<Implementation> pimpl;
};
// Interface.cpp
class Implementation {
public:
void PrivateMember();
};
void Interface::publicMethod() { pimpl->PrivateMember(); }
This has the advantage of hiding implementation, at the cost of a single pointer indirection, not much different from the typical inheritance-based Factory pattern.
This can also be ABI stable. Changes to your implementation won't affect linkage, since no changes will ever be visible to the rest of the program. This is a good pattern to use when implementing shared objects, for example.
It's also a common C++ idiom, so other C++ programmers will recognize it without question.
In the case of a class which will follow the Singleton pattern, you can avoid exposing the PIMPL at all, and simply write the entire implementation in an anonymous namespace in your .cpp file, where you can put as much state and private functions as you wish, without even hinting at it in your interface.
You can create a publicly-visible interface. Create an abstract class with the functions you want to expose, then have your implementation extend it.
For example, an interface:
class Interface {
public:
virtual void publicMethod() = 0;
...
};
And the implementation:
class Implementation : Interface {
public:
virtual void publicMethod();
private:
int hiddenMethod();
};
Then you only export the symbols for Interface. Now, in order for the user of the library to get instances of Interface which are actually Implementations, you need to provide a factory:
class Factory {
public:
//can create and return an Implementation pointer, but caller will get an Interface pointer
std::shared_ptr<Interface> getImplementationInstance();
}
Base on Eric Finn's answer, you can just declare an interface class to hold all your public methods which considered to be your API, and hide all implementations and private members/methods in implementation class which inherits interface class, here's the example:
Your header file: my_api.h
// your API in header file
// my_api.h
class interface {
public:
static interface* CreateInstance();
virtual void draw() = 0;
virtual void set(int) = 0;
};
your implementation(shared library): my_api.cpp (users won't see this when you make it a shared library)
So you can hide all your implementation and private methods/members here
#include "my_api.h"
// implementation -> in .cc file
class implementation : public interface {
int private_int_;
void ReportValue_();
public:
implementation();
void draw();
void set(int new_int);
};
implementation::implementation() {
// your actual constructor goes here
}
void implementation::draw() {
cout << "Implementation class draws something" << endl;
ReportValue_();
}
void implementation::ReportValue_() {
cout << "Private value is: " << private_int_ << endl;
}
void implementation::set(int new_int) {
private_int_ = new_int;
}
interface* interface::CreateInstance() {
return new implementation;
}
How user uses your API:
#include <iostream>
#include "my_api.h"
int main(int argc, const char * argv[])
{
using namespace std;
interface* a; interface* b;
a = interface::CreateInstance();
a->set(1);
b = interface::CreateInstance();
b->set(2);
b->draw();
a->draw();
return 0;
}
Output:
Implementation class draws
Private int is: 2
Implementation class draws
Private int is: 1
In this pattern, your api is just an abstract class which works like a factory, you can also implement the virtual method in different classes and specify which instance you would like to call.
I think you need to create Dynamic Link Library (dll).
Please take a quick look at this link:
You might want to take a look at the envelope/letter idiom, bridge design pattern, or proxy pattern. Basically, you would create an outer (public) class that would just forward your public method calls to the inner (private) class. Your InnerClass.h header only needs to be visible/known to your OuterClass.cpp and InnerClass.cpp source files.
Each of these patterns provides a mechanism of separating the implementation from the interface so that the caller is not coupled to the implementation. Sometimes this is desired to reduce compiler dependencies on large C++ projects. Another common reason for wanting to do this is just when you want to hide the implementation details so that the caller only sees a single opaque pointer.
======= OuterClass.h =====
class InnerClass; // forward declaration is all that's needed
class OuterClass {
private:
InnerClass *pInner;
public:
InnerClass();
bool doSomething();
};
======= OuterClass.cpp ======
#include "OuterClass.h"
#include "InnerClass.h"
OuterClass::OuterClass() :
pInner(new InnerClass())
{
}
bool OuterClass::doSomething()
{
return pInner->doSomething();
}
There actually is a way to do this without having to use classes. I had the same issue and here is a very simple solution:
Just put your private things into the .cpp file. Your header file will look something like this:
// These will be visible to everyone using this library
void function();
int someNumber = 2;
and your .cpp file:
void function() {
// whatever this function does
}
// This will be only visible to the library itself
static void secretFunction() {
doSomeSecretStuff;
}
static int PIN = 1234;
// Okay, if you write this Number into your library and expect it to be safe,
// then screw you, but at least no one will be able to access it with code
When calling the "public" functions from outside you now don't need any instance of that class anymore: Just place the library in the correct directory and include it, but you probably have already taken care of that) and call the functions by their names in the Lib.h file. In the instance of this example it would look something like this:
#include "Lib.h"
int main(int argc, const char * argv[]) {
function();
return 0;
}
Thanks to Edgar Bonet for helping me find this solution on the Arduino Stackexchange!

Creating a list that has to be accessed by the classes it uses C++

I need to create a global list that can be accessed and used by a group of classes that I have initialised, but those classes need to be included to create the list. Any ideas?
Example:
class Game_object
{
public:
~Game_object()
void Update();
void Render();
//Other stuff
};
class Explosion
{
Stuff
};
class Player
{
Stuff
};
All of these classes need to access the list below, that is in another header file, as well as my int main
std::list <Game_object *> Objects;
std::list <Explosion *> Explosions;
And so on.
The idea was that I could create an explosion instance in the destructor of the Game_object, and place it inside of the list. This was so I could have it rendering and updating inside of main
You mean Game_object should hold a std::list<Explosion *> and Explosion should hold a std::list<Game_object *>? It sounds like a job for forward declarations:
#include <list>
class Game_object;
class Explosion;
class Game_object
{
std::list<Explosion *> l;
};
class Explosion
{
std::list<Game_object *> l;
};
This works because your lists contain pointers, not actual objects.
Declare your lists in a header file (for example, mylists.h) like this:
#include <list>
#include <myGameClasses.h>
class Game_object;
class Explosion;
extern std::list<Game_object*> Objects;
extern std::list<Explosion*> Explosions;
// And so for other lists
Using extern will create a referencing declaration for your lists. You should then create the defining declarations in a source file (for example, mylists.cpp):
#include "mylists.h"
std::list<Game_object*> Objects;
std::list<Explosion*> Explosions;
// And so for other lists
Why should you do it like this? This is to prevent multiple declarations when including your header (mylists.h). Only one declaration will then be necessary which, in this case, in the source file (mylists.cpp).
To be able to use the lists, just include the header file.
Also, in mylists.h, there is also a need to for forward declarations of your classes:
class Game_object;
class Explosion;
This is to avoid an undeclared identifier errors.
Maybe it's no good idea to access these lists but if you need this kind of acces you can do it by many ways, the most simple by global variables:
// forward declare Game_object:
class Game_object;
// Declare lists:
typedef std::list <Game_object *> ListObjects;
typedef std::list <Explosion *> ListExplosions;
ListObjects Objects;
ListExplosions Explosions;
class Game_object
{
public:
void Update()
{
// Update Objects...
for (ListObjects::const_iterator O = Objects.begin(); O != Objects.end(); ++O)
{ ... };
// Update Explosions...
for (ListExplosions::const_iterator E = Explosions.begin(); E != Explosions.end(); ++E)
{ ... };
};
void Render()
{
// Render Objects...
for (ListObjects::const_iterator O = Objects.begin(); O != Objects.end(); ++O)
{ ... };
// Render Explosions...
for (ListExplosions::const_iterator E = Explosions.begin(); E != Explosions.end(); ++E)
{ ... };
};
//Other stuff
};
It isn't a good idea, the global variables could be troublesome, even worse with global lists that can be accessed by some other classes and alter its contents while another class try to alter the contents at the same time; but if you're not using threads it couldn't be that troublesome.
Other approach could be to create a manager. The manager must be the owner of the list and would need the methods Setters, Getters, and Deleters methods. To update the contents of the list you can pass a reference to the manager to a renderer/updater and get a reference to the list from the manager:
class ObjectManager
{
public:
typedef std::list <Game_object *> ListObjects;
void AddObject(const ObjectStuff &os)
{ ... };
const ListObjects &GetObjects()
{ return Objects; };
private:
ListObjects Objects;
}
class ExplosionManager
{
public:
typedef std::list <Explosion *> ListExplosions;
void AddExplosion(const ExplosionStuff &es);
{ ... };
const ListExplosions &GetExplosions()
{ return Explosions; };
private:
ListExplosions Explosions;
}
void Render(const ObjectManager &om)
{
// Ask ObjectManager for the object list
}
void Render(const ExplosionManager &em)
{
// Ask ExplosionManager the explosion list
}
The above code is a naive and pretty simple approximation but is only for example purposes. The advantage of the above approach is that the list is modified only by the owner object, if the list is needed out of the manager is provided in a read-only manner and if you are using threads, is pretty simple to add the locks and unlocks in the manager methods in order to avoid the modifications while the list is used.
This isn't asked but I think is worth to say: Could be a good idea to avoid storing object pointers into containers and change the store type by object instances:
std::list <Game_object *> VS std::list <Game_object>
When you're using pointers you must take care of the allocation and deallocation of the objects, if the lists are global you'll need a public Close method to deallocate all the memory managed by the pointers stored in the lists, if the list is owned by some object, you need to do the same process into the object destructor.
But, if you're storing object instances, the list destructor deallocates all the objects stored when it's lifetime ends, the code is cleaner and easier to maintain.

How to store data what needs to be accessible by all members?

I have the following problem (just learning OOP style C++): I have 3 classes:
app
objectManager
object
The app class sets up startup variables and creates an instance of objectManager. It tells objectManager to load values from different files and to precalculate some data in a vector what will be required for each object.
My problem is the following: I would like to use a precalculated vector accessable for each object. I don't understand how can I possibly access this variable from the objects, as they know absolutely nothing about the manager's instance.
I've read about singletons but I have no idea how should I implement it.
I've read about static data members but AFAIK it seems that I still have to somehow connect to the objectManager instance, so it doesn't help me.
I've tried global variables (I know...), but ended up with compiling errors.
I've tried to put static variables outside of a class definition in objectManager.h (is it a global case?), and I ended up with something strange:
I can access the variables from all parts of the program what includes objectManager.h, but it's value is different/uninitialized in different classes.
objectManager.h
#pragma once
#include "Object.h"
static int xxxtest;
class objectManager
{
objectManager.cpp
xxxtest = 123456;
cout << xxxtest << endl;
-> 123456
while in object.cpp or app.cpp (after)
cout << xxxtest << endl;
-> 0
Can you explain to me what is happening here?
Can you recommend me a simple and clean way of organizing such a program, while making a precalculated variable accessable to other parts of the program?
Static class variables are in fact the solution.
Static variables in classes need to be declared in the CPP file, right after the include.
Header:
class Class {
static int staticVariable;
static void staticFunction();
//...
};
CPP:
int Class::staticVariable = 5;
Do that, and all Object instances have access to the static variable (if it's private) and all members of the entire Program can access it (if it's public) by stating:
int Value = Class::staticVariable;
I hope this helps shed some light.
Ah yeah, I used the code from http://de.wikibooks.org/wiki/C++-Programmierung:_Statische_Elemente_in_Klassen (Page is in German) as Reference.
To get back to your problem, that would mean:
Header:
class objectManager {
static std::vector<double> Precompiled;
};
CPP:
std::vector<double> Precompiled; //Initialized automatically.
Since you only intend to create one objectManager, it is a candidate for a singleton or a regular global. As a global, you could define a header file like this:
// in object_manager.hpp
class App;
class ObjectManager;
class ObjectManagerImpl;
ObjectManager & objectManager ();
class ObjectManager {
friend ObjectManager & objectManager ();
friend class App;
std::unique_ptr<ObjectManagerImpl> impl_;
ObjectManager ();
void read_files (std::string file1, std::string file2);
public:
std::vector<int> & precomputed ();
//...
};
And in your source file, you could have something like:
// in object_manager.cpp
class ObjectManagerImpl {
friend class ObjectManager;
std::vector<int> precomputed_;
//...
};
ObjectManager::ObjectManager () : impl_(new ObjectManagerImpl) {}
void ObjectManager::read_files (std::string file1, std::string file2) {
//...
}
std::vector<int> & ObjectManager::precomputed () {
return impl_->precomputed_;
}
//...
ObjectManager & objectManager () {
static ObjectManager instance;
return instance;
}
Now, in the source file of your object, you would include the header file for objectManager, and access the vector through the accessor.
// in object.cpp
//...
std::vector<int> &precomputed = objectManager().precomputed();