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.
Related
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();
I am working on a little game engine but I got stuck at something. Explanation : I have two classes, cEntity And ObjectFactory :
cEntity
class cEntity:public cEntityProperty
{
Vector2 position;
Vector2 scale;
public:
cEntity(void);
cEntity(const cEntity&);
~cEntity(void);
public:
void init();
void render();
void update();
void release();
};
ObjectFactory
#include "cEntity.h"
#include <vector>
class ObjectFactory
{
static std::vector<cEntity> *entityList;
static int i, j;
public:
static void addEntity(cEntity entity) {
entityList->push_back(entity);
}
private:
ObjectFactory(void);
~ObjectFactory(void);
};
std::vector<cEntity> *ObjectFactory::entityList = new std::vector<cEntity>();
Now I am adding new cEnity to ObjectFactory in cEntity constructor but facing an error related to circular references: for using ObjectFactor::addEntity() I need to define the ObjectFactory.h in cEntity class but it creates a circular reference.
I think your code might have an underlying architectural issue given how you have described the problem.
Your ObjectFactory should be handling the cEntities, which in turn should be unaware of the "level above". From the description of the problem you are having, it implies that you're not sure what class is in charge of what job.
Your cEntitys should expose an interface (i.e. all the stuff marked "public" in a class) that other bits of code interact with. Your ObjectFactory (which is a bit badly named if doing this job, but whatever) should in turn use that interface. The cEntitys shouldn't care who is using the interface: they have one job to do, and they do it. The ObjectFactory should have one job to do that requires it to keep a list of cEntitys around. You don't edit std::string when you use it elsewhere: why is your class any different?
That being said, there's two parts to resolving circular dependencies (beyond "Don't create code that has circular dependencies in the first place" - see the first part to this answer. That's the best way to avoid this sort of problem in my opinion)
1) Include guards. Do something like this to each header (.h) file:
#ifndef CENTITY_H
#define CENTITY_H
class cEntity:public cEntityProperty
{
Vector2 position;
Vector2 scale;
public:
cEntity(void);
cEntity(const cEntity&);
~cEntity(void);
public:
void init();
void render();
void update();
void release();
};
#endif
What this does:
The first time your file is included, CENTITY_H is not defined. The ifndef macro is thus true, and moves to the next line (defining CENTITY_H), before it moves onto the rest of your header.
The second time (and all future times), CENTITY_H is defined, so the ifndef macro skips straight to the endif, skipping your header. Subsequently, your header code only ever ends up in your compiled program once. If you want more details, try looking up how the Linker process.
2) Forward-declaration of your classes.
If ClassA needs a member of type ClassB, and ClassB needs a member of type ClassA you have a problem: neither class knows how much memory it needs to be allocated because it's dependant on another class containing itself.
The solution is that you have a pointer to the other class. Pointers are a fixed and known size by the compiler, so we don't have a problem. We do, however, need to tell the compiler to not worry too much if it runs into a symbol (class name) that we haven't previously defined yet, so we just add class Whatever; before we start using it.
In your case, change cEntity instances to pointers, and forward-declare the class at the start. You are now able to freely use ObjectFactory in cEntity.
#include "cEntity.h"
#include <vector>
class cEntity; // Compiler knows that we'll totally define this later, if we haven't already
class ObjectFactory
{
static std::vector<cEntity*> *entityList; // vector of pointers
static int i, j;
public:
static void addEntity(cEntity* entity) {
entityList->push_back(entity);
}
// Equally valid would be:
// static void addEntity(cEntity entity) {
// entityList->push_back(&entity);}
// (in both cases, you're pushing an address onto the vector.)
// Function arguments don't matter when the class is trying to work out how big it is in memory
private:
ObjectFactory(void);
~ObjectFactory(void);
};
std::vector<cEntity*> *ObjectFactory::entityList = new std::vector<cEntity*>();
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!
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];
}
};
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.