Edit For Clarification:
Is there a way to split a class's header across multiple files, such that other classes can include only the parts of that class's implementation it's supposed to be allowed to use?
----Below is specific details to my desired implementation:---- NOT A NECESSARY READ!
Anyways, I'm creating an entity-component system. I would like to structure it as follows:
There is an 'EntityPool' object that exists mainly as a memory store/manager for entities and their components. I would like to have a specified degree of access from my 'Game' class (for example, the ability to construct/destruct the pool, and the ability to access arrays of components ei the ability to iterate through all 'renderable' components).
There is a base class of 'EntityFactory' that I would like to have a greater degree of access to the entity pool. It would be used by the 'Game' class as follows:
GruntEntityFactory ef(&EntityPool); //GruntEntityFactory inherits from EntityFactory
ef.produce();
The Entity Factory would then use its access to the Entity Pool to create the necessary components and put them in place.
The thing to note here is that 'Game' would have access only to create the EntityPool and read its contents, but would NOT be able to directly alter its contents. Everything that inherits EntityFactory, on the other hand, I would like to give access to manage EntityPool's contents.
Is there a way I can include a different EntityPool header in each of the files, such that each is only 'aware' of the functions it has access to? Is that the best way to do this (assuming it's possible)?
Also- I realize this tightly couples the EntityPool and EntityFactories. That is intentional. And also, I would like to not have to list every EntityFactory I make as a friend class in EntityPool.
Thanks!
Example code for clarification
//In my Game Class
#include "entitypool.h"
#include "entityfactory_grunt.h"
...
EntityPool ep(); //Construct an EntityPool
GruntEntityFactory gef(&ep); //Pass an EntityPool pointer to an EntityFactory
gef.produce(); //Call produce on GruntEntityFactory, and have it add appropriate components to the EntityPool
//I would like this next line to not be allowed. Game shouldn't be able to
//directly manipulate the components/ other internal EntityPool structure.
//However, I WOULD like EntityFactories to retain the ability to do so.
//(otherwise, how would EntityFactory.produce() work?)
ep.addComponent(PhysicsComponent pc(1, 2, 3));
//I WOULD like Game to be able to access certain functions of EntityPool
for(int i = 0; i < ep.numPhysicsComponents; i++)//Like the count of entities
physicsSolver.update(ep.physicsComponents[i]);//And the ability to update/render components
Ok. So hopefully that's sensible enough of an example to get an idea for what I want. The reason for the title is that my first intuition on how to achieve this would be to have 2 header files.
//EntityPool_GameAccess.h
//This file would contain prototypes for the functions utilized by Game, but NOT the ones
//that game is not allowed to see.
class EntityPool
{
public:
int numPhysicsComponents();
PhysicsComponent getPhysicsComponent(int i);
};
and
//EntityPool_FactoryAccess.h
//This file would contain prototypes for the functions that only ought be used
//by classes specifically built to manipulate entitypool
class EntityPool
{
public:
void addPhysicsComponent(PhysicsComponent pc);
int numPhysicsComponents();
PhysicsComponent getPhysicsComponent(int i);
};
Obviously these examples are simplified. Hopefully I'm still getting the idea across: I would like a class with certain functions that are accessible to certain classes, and other functions that are accessible to other classes.
Ok. I've finally found an answer in another question on StackOverflow: Making classes public to other classes in C++
The bottom part of Patrick's answer:
Unfortunately, there is no way in C++ to make only a part of your class public to a limited set of other classes.
Related
In my simulation I have different objects that can be sensed in three ways: object can be seen and/or heard and/or smelled. For example, Animal can be seen, heard and smelled. And piece of Meat on the ground can be seen and smelled but not heard and Wall can only be seen. Then I have different sensors that gather this information - EyeSensor, EarSensor, NoseSensor.
Before state: brief version gist.github.com link
Before I started implementing NoseSensor I had all three functionality in one class that every object inherited - CanBeSensed because although classes were different they all needed the same getDistanceMethod() and if object implemented any CanBeSensed functionality it needed a senseMask - flags if object can be heard/seen/smelled and I didn't want to use virtual inheritance. I sacrificed having data members inside this class for smell, sounds, EyeInfo because objects that can only be seen do not need smell/sound info.
Objects then were registered in corresponding Sensor.
Now I've noticed that Smell and Sound sensors are the same and only differ in a single line inside a loop - one calls float getSound() and another float getSmell() on a CanBeSensed* object. When I create one of this two sensors I know what it needs to call, but I don't know how to choose that line without a condition and it's inside a tight loop and a virtual function.
So I've decided to make a single base class for these 3 functionality using virtual inheritance for base class with getDistanceMethod().
But now I had to make my SensorBase class a template class because of this method
virtual void sense(std::unordered_map<IdInt, CanBeSensed*>& objectsToSense) = 0;
, and it meant that I need to make SensorySubSystem class(manages sensors and objects in range) a template as well. And it meant that all my SubSystems like VisionSubSystem, HearingSubSystem and SmellSubSystem inherit from a template class, and it broke my SensorySystem class which was managing all SensorySubSystems through a vector of pointers to SensorySubSystem class std::vector<SensorySubSystem*> subSystems;
Please, could you suggest some solution for how to restructure this or how to make compiler decide at compile time(or at least decide once per call//once per object creation) what method to call inside Hearing/Smell Sensors.
Looking at your original design I have a few comments:
The class design in hierarchy.cpp looks quite ok to me.
Unless distance is something specific to sensory information getDistance() doesn't look like a method that belongs into this class. It could be moved either into a Vec2d-class or to a helper function (calculatePositon(vec2d, vec2d)). I do not see, why getDistance() is virtual, if it does something different than calculating the distance between the given position and the objects position, then it should be renamed.
The class CanBeSensed sounds more like a property and should probably be renamed to e.g. SensableObject.
Regarding your new approach:
Inheritance should primarily be used to express concepts (is-a-relations), not to share code. If you want to reuse an algorithm, consider writing an algorithm class or function (favour composition over inheritance).
In summary I propose to keep your original class design cleaning it up a little as described above. You could add virtual functions canBeSmelled/canBeHeard/canBeSeen to CanBeSensed.
Alternatively you could create a class hierachy:
class Object{ getPosition(); }
class ObjectWithSmell : virtual Object
class ObjectWithSound : virtual Object
...
But then you'd have to deal with virtual inheritance without any noticeable benefit.
The shared calculation code could go into an algorithmic class or function.
I'm fairly new to c++ templates.
I have a class whose constructor takes two arguments. It's a class that keeps a list of data -- it's actually a list of moves in a chess program.
I need to keep my original class as it's used in other places, but I now need to pass extra arguments to the class, and in doing so have a few extra private data members and specialize only one of the private methods -- everything else will stay the same. I don't think a derived class helps me here, as they aren't going to be similar objects, and also the private methods are called by the constructor and it will call the virtual method of the base class -- not the derived method.
So I guess templates are going to be my answer. Just looking for any hints about how might proceed.
Thanks in advance
Your guess is wrong. Templates are no more the answer for your problem than inheritance is.
As jtbandes said in comment below your question, use composition.
Create another class that contains an instance of your existing class as a member. Forward or delegate operations to that contained object as needed (i.e. a member function in your new class calls member functions of the contained object). Add other members as needed, and operations to work with them.
Write your new code to interact with the new class. When your new code needs to interact with your old code, pass the contained object (or a reference or a pointer to it) as needed.
You might choose to implement the container as a template, but that is an implementation choice, and depends on how you wish to reuse your container.
Templates are used when you want to pass at compile time parameter like values,typenames, or classes. Templates are used when you want to use exactly the same class with the same methods, but applying it to different parameters. The case you described is not this I think.
If they aren't goign to be similar objects you may want to create a specialized class (or collections of function) to use from the various other classes.
Moreover you can think of creating a base class and extending it as needed. Using a virtual private method should allow you to select the method implementation of the object at runtime instead of the method of the base class.
We may help you more if you specify what does they need to share, what does your classes have in common?
The bare bones of my present code looks like this:
class move_list{
public:
move_list(const position& pos, unsigned char ply):pos_(pos),ply_(ply){
//Calculates moves and calls add_moves(ply,target_bitboard,flags) for each move
}
//Some access functions etc...
private:
//private variables
void add_moves(char,Bitboard,movflags);
};
Add_moves places the moves on a vector in no particular order as they are generated. My new class however, is exactly the same except it requires extra data:
move_list(const position& pos, unsigned char ply,trans_table& TT,killers& kill,history& hist):pos_(pos),ply_(ply),TT_(TT),kill_(kill),hist_(hist) {
and the function add_moves needs to be changed to use the extra data to place the moves in order as it receives them. Everything else is the same. I guess I could just write an extra method to sort the list after they have all been generated, but from previous experience, sorting the list as it receives it has been quicker.
I need to create simulation of parabolic flight of bullet(simple rectangle), and one of conditions is to make all calculation inside self-made library and to create for it interface(abstract class).
Am confused how to implement this:
Make fully abstract class and couple of functions(not methods in
class) that will use class through "get()" and "set()"?
Make class with all calculations implemented in his methods, and just
make one "draw" method pure virtual?
I'm using WinAPI, and all graphics through GDI
and will be really appreciate for any help
One of the purposes you create classes for is to separate all unrelative data and operations to the different classes.
In your case one part is calculations and the other part is result layout.
So, the best way to implement it is to define a class which provides all calculations and access to results and implement the drawing function, which will use the object of your calculation class.
Thus, it will be able to use your calculations in other environment (for example, in some your other project) without any code changing, which is natural. It will provide portability of your platform-independent caclulation code.
And the layout part, which is platform-dependent, should be implemented separatly, using just interface, which is provided by the calculation class.
class Trajectory
{
public:
// Constructor, computation call methods
// "GetResult()" function,
// which will return trajectory in the way you choose
...
private:
// computation functions
};
// somewhere else
void DrawTrajectory(Trajectory t)
{
// here is a place for calling all winapi functions
// with data you get using t.GetResult()
}
If abstract class is required you should inherit Trajectory class from an abstract class,
where you will define all functions you have to call.
In this case
//
class ITrajectory
{
public:
// virtual /type/ GetResult() = 0;
// virtual /other methods/
};
class Trajectory : public ITrajectory
{
// the same as in previous definition
};
void DrawTrajectory(ITrajectory T)
{
// the same as in previous definition
}
When you are talking about Windows, libraries, and abstract classes as interfaces, I wonder if you are thinking of sharing classes between DLLs.
There is a declspec(dllexport) keyword, but using this on classes and/or class members is bad. You end up with all your library code closely coupled and completely dependent on using the same compiler version and settings for everything.
A much better option, which allows you to upgrade compiler for one DLL at a time, for instance, is to pass interface pointers. The key here is that the consumer of the library knows nothing about the class layout. The interface doesn't describe data members or non-virtual functions which might get inlined. Only public virtual functions appear in the interface, which is just a class defined in the public header.
The DLL has the real implementation which inherits from the interface. All the consumer has is the virtual function table and a factory (plain old C-compatible function) which returns a pointer to a new object.
If you do that, you can change the implementation any way you like without changing the binary interface which consumers depend on, so they continue to work without a recompile. This is the basis of how COM objects work in Windows.
So, a quick summary of why I'm trying to do this:
I'm making a space flight program, wherein (once I code in more than one ship) I will be able to store different ships, e.g. craft[HAB], craft[AYSE], craft[ISS], and so forth. At the moment, I have only coded in one ship, and I declare it like so:
enum craft {HAB, CRAFTMAX};
...
[declaring ship class here]
...
ship craft[CRAFTMAX];
However, not all ships will be the same structure. For example, HAB (short for Habitat) will be a circle with three engine pods on the bottom, AYSE will be a space station with a tube going to the centre, and docking lights, and so forth. I am making these functions draw a vector to the screen.
At the moment, I have declared ship::draw, and I just use this to draw the Hab. However, I want to be able to modify each draw function to draw that ship, i.e. craft[AYSE].draw() will have a different declaration than craft[HAB].draw().
I've thought, and looked up different ways to do this, but I haven't gotten much success. I'd still like to be able to iterate through all the crafts for ease of calculating gravity and collisions. But I'm guessing if it's impossible to individually declare functions when they are elements of an array, it won't be too much trouble to declare each ship individually, as there will only be 10, max.
Here is my git repository that is storing this, if you want to take a look at any other code. It is definitely a bit unorganized, as it is a monopoly project, and I only ever see myself using it.
Any of you tried to do this? I'm sure there must be a few people out there!
And thanks in advance.
I think you will be much better by using a base class for a Ship object, then deriving from this base class for the different types of ships. Then use some container that allows you to iterate through all ship objects and call the respective functions. Like:
class Ship {
public:
virtual void draw() const = 0;
};
class HAB : public Ship {
virtual void draw() const;
};
class AYSE : public Ship {
virtual void draw() const;
};
Then using a container like:
vector<Ship> ships;
ship.insert(HAB());
ship.insert(AYSE());
// to draw
for_each(ships.begin(), ships.end(), mem_fn(&Ship::draw));
I came up with this fairly quick so you will have to work out the details. The way you are thinking of doing it is not very OO and will have problems in terms of maintenance (think Single Point of Maintenance).
I don't like the look of your code - using the word craft as both a type identifier and a variable identifier...
But from your question it looks like you want to use inheritance. So you declare a
class ship {
// put here all methods that all ships have and that are the same
// and all data that all ships.
virtual void Draw( ) = 0; // subclasses of ship are forced to implement their own Draw
// etc.
};
Now when you want an array of ships, make it an array of pointers to ship. You can then put in pointers to the subclasses, and use dynamic_cast to get pointers back to the subclasses when you need them. But by calling A[4]->Draw() you will get whatever Draw routine is appropriate for the object in location 4 of the array.
The OO way would be to create a hierarchy of types, with each type representing one of the types of aircrafts. Use virtual functions to provide different implementations for the common interface (declared in the base class).
Once you have this, you will need to store the objects in the container polymorphically (i.e. not the object, but rather a smart pointer to the objects). The (smart) pointers would be of the base type and the objects of the actual types. I would recommend that you use a higher level container rather than arrays (i.e. std::vector<std::unique_ptr<ship>>)
You'll probably want to declare a base class and implement each type of ship as child classes.
class HAB: public ship{
//code here
};
For more information on inheritance: see this tutorial.
The colon shows that HAB inherits member data and function from the class ship. This way you can define some functions uniquely in each of the child classes while still having them share important functions with the base class. For example each ship type is likely to have similar member functions like get_position() whereas a draw function depends specifically on each ship type.
The beauty of polymorphism is that you can refer to the child classes as their parent class. So you can make an array of ship * (ship pointers) to refer to an array of child classes.
ship * array[CRAFTMAX];
array[0]=new HAB;
However before using this sort of thing you should be really up on your pointers because mismanagement can result in memory leaks. That is, you allocate memory and never free it up.
This website has some nice instruction in polymorphism.
I have a couple of base/interface classes each of which has several derived classes. I have a need to store metadata on each derived class that has a lot of overlap, but different values.
I also have a Factory class for creating instances of the derived classes that's implemented as a singleton and has a few macros. For example, you'd:
REGISTER_COMPONENT("MyComponent", MyComponentClass);
// create an instance of each component
BaseComponent *base;
foreach(QString component, ComponentRegister::componentList())
{
base = ComponentRegister::create(component);
// do stuff with base
}
The question is: how and where to store the metadata from a solid design viewpoint.
I could store the data in the ComponentRegister as a QMap structure. When someone registers a component, they could also register its metadata with something like
REGISTER_COMPONENT_METADATA("MyComponent", MyMap);
If the QVariant::isValid() for a particular key, you know the metadata is set and available.
Another way would be static class variables or maybe a static class QMap.
I see advantages and draw backs to both. Most of the metadata are things like "path to QResources for this class" which is not tightly coupled to the business logic of the class itself.
Another issue with the static class variable method comes into play with inheritance. You can't enforce overriding of static class variables like you can with pure virtual functions. So if someone forgets...it could be unclear where in the inheritance tree the values are coming from. If you require access to the metadata through a series of pure virtual "getters" then setting of the MetaData is spread across all implementations of the Base class.
With data held, set, and looked up in the Register if you needed to make changes (like changing the root path for resources), you could do so at a single point...in the class registration calls, probably a header or wrapped in a application Utility function. With static data, you'd have to edit each class declaration.
Open to suggestions and thanks!
If data related to an object isn't specific to a single instance, as the path in your example, my designs usually include a class which manages my collection of objects. That's where I put the meta data.
example:
class zoo { std::vector<animals> zoo_animals; size_t count; }
count is metadata about the animals.