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.
Related
Context
The context is composed by three classes:
abstract parent (e.g. Player)
child (e.g. TapePlayer)
a holder (e.g. MyMachine)
The holder has a member variable that is a shared_ptr<...> to the parent class and a setter for it accepts shared_ptr<...>s of children classes.
My getter looks something like this
shared_ptr<Parent> getChildPtr() {
return parentPtr;
};
but it returns a pointer to the parent, and cannot access child methods.
If I want to do something like the following
holder.getChildPtr()->childMethod();
// ERROR! No member named 'childMethod' in 'Parent'
How should I implement the getter to get the pointer to the child instead of the parent class?
Code
The whole code looks something like this:
class Player {
public:
Player(){};
virtual ~Player{};
virtual void play() = 0;
}
class TapePlayer : public Player {
public:
TapePlayer(){};
virtual ~TapePlayer{};
void play() { ... };
void rewind() { ... };
}
class MyMachine {
public:
MyMachine(); //
~MyMachine();
void setPlayer(shared_ptr<Player> p) {
playerPtr = p;
}
shared_ptr<Player> getPlayer() {
return playerPtr;
};
private:
shared_ptr<Player> playerPtr;
}
MyMachine machine; // the holder
shared_ptr<TapePlayer> tapePtr(new TapePlayer()); // pointer to child
machine.setPlayer(tapePtr); // set holder with pointer to child
machine.getPlayer()->rewind(); // -- ERROR! No member named 'rewind' in 'Player'
// if I want to get the player of that machine to rewind I need
// to dynamic_cast<TapePlayer>() ...
I'm pretty sure there's a better way of doing this than casting to children types. Any ideas?
EDIT
This was a very simplified example. What I'm actually trying to do is this:
My holder class is named Clip. A clip plays something, be it an
image, a video, a sequence of images, some kind of processing with
OpenCv, a vector shape... anything that can be displayed.
All these types of things are Players.
I don't care what type of player the clip holds. I just want it to show it to me. But, some players need tweaking at runtime, like the OpenCv one, that needs tweaking parameters for optimal processing. I cannot implement all methods of all subclasses in the parent class, that would make no sense to me. Why does a video need to have the methods for tweaking OpenCv parameters?
All I need is that both have 'playable' methods, and be able to store them in a map<string, PlayerPtr> to access them at any time or change the player the clip is holding.
The point is that this kind of ruins the polymorphism - even with dynamic_cast, you still need to check that the result is not 0 (i.e. check the actual type) and as you might already know, dynamic_cast is famous for being very slow (and requiring RTTI information built in the executable).
Is there any reason you couldn't add a pure virtual rewind() method to your Player interface? Then you'd just call it and the inherited class could do whatever it decides in that case. Other subclasses might implement it as empty (or it can be even empty by default in the Player itself, so that the subclasses do not have to implement it if they don't need to). Perhaps even some more "generic" virtual function like reset(), restart() etc. which would just call rewind() for the TapePlayer under the hood.
You can of course go even more fancy with more complex solutions like visitor/observer (TapePlayer being RewindObserver and observing a rewind event) etc.
EDIT:
So to address the edit comments - if the different types need tweaking, then again, you can just have a single virtual method tweak() (pure or with default empty impl) and do whatever tweaking is needed. Otherwise you'd anyway end up with a long list of ifs and call tweak methods depending on the actual type.
If the tweaking requires some special parameters, then the situation can be difficult ... one option could be to have a tweaking parameters interface (and call the tweak method with that), but if the params can't be unified you'd need a dynamic cast in the tweak method anyway to cast to the correct params type (this basically leads to double dispatch which in C++ requires casting at some point) ... but anyway that would still require to create different param classes in the calling site which is not that nice.
It also depends when you actually need to setup the tweaking parameters - if it is enough to setup everything when creating the instance (and the tweaking params do not change afterwards), or if it is needed to change them later on. If only needed to setup at startup, then you can have factory classes for the different object types and the factory can setup the params.
(technically you could handle even the necessity of changing the params a similar way, by keeping the setting object types for various player types, the players would keep reference to them as well, assigned when the objects are created, and once they need to be changed, you'd change the settings and call tweak() or update() or similar func to inform the objects that some setting changed and needs to be re-applied)
Background Info
I am writing a graph-drawing program. I have encountered a problem with templates and inheritance, and I do not know how to proceed. I do not know how I should design my code to enable me to do what I am trying to do. (Explanation below.)
Target
I have a template class, which represents "data". It looks something like the following:
template<typename T>
class GraphData
{
std::vector<T> data_x;
std::vector<T> data_y; // x and y should be held in separate vectors
}
This class is part of an inheritance hierarchy involving several classes.
The hierarchy looks something like this... (Sorry this is from my notes, awful diagram.)
Explanation
There is a base class. No real reason to have it right now, but I anticipate using it later.
Base_Legend adds functionality for legend drawing. New members added include a std::string, and Get/Set functions.
Base_Drawable adds a pure abstract = 0 member. void Draw(...). This is to force overloading in all inherited objects which are drawable.
GraphData_Generic adds functionality for adding/removing data points to a set of vectors. These are pure abstract methods, and must be overridden by any data classes which inherit.
GraphData and HistogramData are 2 data types which have implementations of the functions from GraphData_Generic. (No implementation of Draw().)
GraphData_GenericDrawable doesn't do anything. It is to be used as a base class pointer, so that a vector of these objects can be used as data (add/remove data points) and can be draw (using void Draw()). This class also can be used to call the Get()/Set() methods for the std::string to be used in the legend.
Finally, at the bottom are GraphData_Drawable and HistogramData_Drawable which overload the void Draw() function. This code specifies exactly how the data should be drawn, depending on whether we have a Histogram or general set of data points.
Problem
Currently, I am using template types. The type of data for the datapoints / histogram bin values is specified by using a template.
For example, one can have a HistogramData<double, HistogramData_Drawable<double>, HistogramData_Drawable<int>, etc... Similarly, one can have GraphData<double>, GraphData<float>, GraphData_Drawable`, etc...
So hopefully it should be fairly obvious what's going on here without me uploading my ~ 10000 lines of code...
Right, so, in addition I have some class Graph, which contains a std::vector<GraphData_Generic_Drawable*>, hence the use of the base class pointer, as suggested above.
BUT! One has to decide what type of data should be used as the underlying type. I MUST choose either std::vector<GraphData_Generic_Drawable<double>*> or std::vector<GraphData_Generic_Drawable<float>*>.
This isn't useful, for obvious reasons! (I could choose double and force the user to convert all values manually, but that's just an easy way out which creates more work later on.)
A (very) ugly solution would be to have a std::vector<> for each possible type... int long unsigned long long double float unsigned char... etc...
Obviously this is going to be hideous and essentially repeat loads of code..
So, I intend to implement an AddData method which adds data to that vector, and I also currently have the following method:
// In class Graph
void DrawAll()
{
for(std::vector<GraphData_Drawable*>::iterator it = m_data.begin(); it != m_data.end(); ++ it)
(*iterator)->Draw(arguments);
} // Draw function takes arguments including a canvas to draw to, but this isn't directly relevant to the question
Which iterates over the vector and calls Draw for each set of data in there.
How to fix it?
My current thoughts are something along the lines of; I need to implement some sort of interface for an underlying data class, which retrieves values independent of the underlying type. But this is only a very vague initial idea and I'm not really sure how I would go about implementing this, hence the question... I'm not sure this is even what I should be doing...
If this isn't clear ask me a question and I'll update this with more details.
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.