I had a really long post on this and decided it can be summed up much shorter. Canonically speaking, is it better to include a data member inside of a class as opposed to inheriting it? I found I can implement identical functions either way, but don't really know what caveats I should be aware of.
Code example
#include "KClass.h"
class KPC : public KCharacter {
private:
KClass MyClass;
};
versus
class KClass : public KCharacter {
};
class KPC : public KClass {
};
In the first example, anytime I needed something from the KClass data, I could access it via MyClass->
In the second class, class KPC would just directly access them since it would inherit the data members.
For specifics to my problem I guess I should detail the class' function.
D&D format. Each character has a class which would determine: weapon/armor proficiencies, bonus defenses, special ability i.e. defender has mark.
So to me, it made sense to inherit it. However, is class a more specific PC or is PC a specific kind of class? There are so many PCs in a game that aren't a specific class, actually class should inherit PC on that concept sense it's more 'specialized' form of a PC. So would I want to structure it in a way of KClass : KPC ?
It seemed easier to implement a Has-A at first, but now I'm second guessing it. Hence the reason why I'm here, asking this question.
Generally speaking, composition is better than inheritance. But it depends on what exactly you want to do. For the most part think:
IS A -> inheritance
HAS A -> composition
Inherit when you want/need to extend a base class. If you just need to use another class, just have an instance of it with the other class.
Side note, composition and aggregation are basically the same thing. Conceptually slightly different, in code, the same thing.
It's a matter of design and what you are trying to model. Scott Meyers' Effective C++ will note that public inheritance (the second example) models 'is-a', whereas composition (the first example) models 'is-implemented-in-terms-of' or 'has-a'. So, for your example, you should decide what role KClass is playing and which of these philosophies makes more sense. Just looking at the names KCharacter, KClass, and KPC, it's hard for me to tell their purposes.
It really depends on what you are trying to do. Yes, both achieve mechanically similar things, but the rule is "is-a" or "has-a" for deciding which way to go.
If KPC really "is-a" form of KClass, then you should use inheritance. This means that you are looking to solve a polymorphic problem - you have several items that are similar:
class AeroPlaneBase
{
...
};
class JetPlane : public AeroPlaneBase
{
...
};
class PropellerPlane : public AeroPlaneBase
{
...
};
class GliderPlane : public AeroPlaneBase
{
};
All of these planes can do similar things - but they behave slightly differently, so they need a different class to describe their behaviour.
Now, each plane will have zero or more "engines", so the class may have a "has-a" relationship to a PlaneEngine class. The glider, which is an engineless plane doesn't have any engine, the JetPlane can have 8, perhaps...
Likewise, in a roleplaying game, a player "is-a" Character (which is also the baseclass for Monster and the different derived forms of that), say, but "has-a" relationship with the Weapon class. The Character isn't a type of Weapon, but it has a weapon.
Conceptual
The concept of classes and objects is usually used to model "real" things. But let's put the cart before the horse.
The transfer of the inheritance concept to the real world would be (like others said) an IS A-relation.
A TFT is a screen
A Fox is an Animal
...
The composition is, in contrast, usually considerd as HAS A-relation.
A PC has a CPU
A knife has a blade
...
So if you want to model the latter in object-oriented programming, make use of composition. In case of the former concept, use inheritance.
Examples
Composition > Inheritance
Examples always tend to come naturally to me. So I'll try to illustrate it a bit further. (No encapsulation here, sorry. ;))
Consider motorvehicles, respectively cars. The tend to have an engine, which has a specific sound.
struct Engine
{
void sound (void) const { std::cout << "BROOOM" << std::endl; }
void open_valve (void) { /* ... */ }
};
Engines also can perform certain engine-specific tasks.
Now we can have both specified options to include the engine into a car: inheritance or composition.
struct Car_A : public Engine { };
At the first moment, this seems appropriate. We don't need to reprovide sound() since a car (in the first approximation) just sounds like an engine.
Car_A a_car;
a_car.sound(); // mycar sounds like a car!
But the noise is not very realistic: No tread noise, no air draft. So we can just shadow the underlying method and define:
struct Car_A : public Engine
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
Engine::sound();
}
};
We still have a slight problem.
a_car.open_valve(); // ?
The concept of valves is part of the engine but not part of the car but we can use this method on the car.
The car has an engine but it isn't one.
We could switch to private inheritance now but the method would still be present, although not accessible.
Another (less conceptual) issue can be seen when using pointers of the types:
Engine * pointer_to_engine(new Car_A); // works
An engine that actually is a car? "(Suspected) Engines" exhibiting car behaviour and vice versa? Well that doesn't look like the way to do things here.
Let's look at composition instead:
struct Car_B
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
engine.sound();
}
void open_door (void) { /* ... */ }
Engine engine;
};
That's how things are supposed to be: A car that has a[n] (member) engine that sounds like an engine and contributes to the sound of the car and no methods are present in the car that are not part of the concept of a car.
Car_B b_car;
b_car.sound(); // still sounds like a car!
b_car.engine.open_valve(); // meaningful for an engine!
Here we have a case where composition is superior.
The "real" situation is modeled.
All concepts keep their validity. (No unintended behaviour.)
Inheritance > Composition
Now we add another Concept in our example: a vehicle.
struct Wheel {};
struct Motorvehicle
{
virtual void sound (void) const { engine.sound(); }
Engine engine;
std::vector<Wheel> wheels;
};
A motorvehicle is driven by an engine, so it knows to emmit engine sound.
However, the abstract vehicle has no clue of how many wheels its concrete objects will have have (motorcycle? car?) or how its shape is formed, so it can't tell anything about tread noise and air draft.
This time we look at composition first (miracle miracle...):
struct Car_C
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
vehicle.sound();
}
Motorvehicle vehicle;
};
Looks legit, doesn't it?
Car_C c_car;
c_car.sound(); // correct sound!
c_car.vehicle.sound(); // what the hell is "the vehicle of a car"?
c_car.wheels.... // error the car has no wheels?!
"Pretending" that wheels are part of the car will require us to add an additional function for our car. If we use inheritance instead, this coherency comes from scratch.
struct Car_D
: public Motorvehicle
{
void sound (void) const
{
std::cout << "tread noise + air draft" << std::endl;
Motorvehicle::sound();
}
};
The observable behaviour of Car_D is more like you would expect it to be.
Car_D d_car;
d_car.sound(); // correct sound!
d_car.wheels.[...] // valid, our car has wheels!
Conclusion
The consideration, whether to use inheritance or composition is not always as easy as in my examples but you should try to weight up and choose the concept that performas better in reflecting the desired behaviour.
If the designated base class describes an abstract generalization of the derived class, this is a good hint for inheritance.
Related
I am a decent procedural programmer, but I am a newbie to object orientation (I was trained as an engineer on good old Pascal and C). What I find particularly tricky is choosing one of a number of ways to achieve the same thing. This is especially true for C++, because its power allows you to do almost anything you like, even horrible things (I guess the power/responsibility adage is appropriate here).
I thought it might help me to run one particular case that I'm struggling with by the community, to get a feel for how people go about making these choices. What I'm looking for is both advice pertinent to my specific case, and also more general pointers (no pun intended). Here goes:
As an exercise, I am developing a simple simulator where a "geometric representation" can be of two types: a "circle", or a "polygon". Other parts of the simulator will then need to accept these representations, and potentially deal with them differently. I have come up with at least four different ways in which to do this. What are the merits/drawbacks/trade-offs of each?
A: Function Overloading
Declare Circle and Polygon as unrelated classes, and then overload each external method that requires a geometric representation.
B: Casting
Declare an enum GeometricRepresentationType {Circle, Polygon}. Declare an abstract GeometricRepresentation class and inherit Circle and Polygon from it. GeometricRepresentation has a virtual GetType() method that is implemented by Circle and Polygon. Methods then use GetType() and a switch statement to cast a GeometricRepresentation to the appropriate type.
C: Not Sure of an Appropriate Name
Declare an enum type and an abstract class as in B. In this class, also create functions Circle* ToCircle() {return NULL;} and Polygon* ToPolygon() {return NULL;}. Each derived class then overloads the respective function, returning this. Is this simply a re-invention of dynamic casting?
D: Bunch Them Together
Implement them as a single class having an enum member indicating which type the object is. The class has members that can store both representations. It is then up to external methods not to call silly functions (e.g. GetRadius() on a polygon or GetOrder() on a circle).
Here are a couple of design rules (of thumb) that I teach my OO students:
1) any time you would be tempted to create an enum to keep track of some mode in an object/class, you could (probably better) create a derived class for each enum value.
2) any time you write an if-statement about an object (or its current state/mode/whatever), you could (probably better) make a virtual function call to perform some (more abstract) operation, where the original then- or else-sub-statement is the body of the derived object's virtual function.
For example, instead of doing this:
if (obj->type() == CIRCLE) {
// do something circle-ish
double circum = M_PI * 2 * obj->getRadius();
cout << circum;
}
else if (obj->type() == POLY) {
// do something polygon-ish
double perim = 0;
for (int i=0; i<obj->segments(); i++)
perm += obj->getSegLength(i);
cout << perim;
}
Do this:
cout << obj->getPerimeter();
...
double Circle::getPerimeter() {
return M_PI * 2 * obj->getRadius();
}
double Poly::getPerimeter() {
double perim = 0;
for (int i=0; i<segments(); i++)
perm += getSegLength(i);
return perim;
}
In the case above it is pretty obvious what the "more abstract" idea is, perimeter. This will not always be the case. Sometimes it won't even have a good name, which is one of the reasons it's hard to "see". But, you can convert any if-statement into a virtual function call where the "if" part is replaced by the virtual-ness of the function.
In your case I definitely agree with the answer from Avi, you need a base/interface class and derived subclasses for Circle and Polygon.
Most probably you'll have common methods between the Polygon and Circle. I'd combine them both under an interface named Shape, for example(writing in java because it's fresher in my mind syntax-wise. But that's what I would use if I wrote c++ example. It's just been a while since I wrote c++):
public interface Shape {
public double getArea();
public double getCentroid();
public double getPerimiter();
}
And have both Polygon and Circle implement this interface:
public class Circle implements Shape {
// Implement the methods
}
public class Polygon implements Shape {
// Implement the methods
}
What are you getting:
You can always treat Shape as a generelized object with certain properties. You'll be able to add different Shape implementations in the future without changing the code that does something with Shape (unless you'll have something specific for a new Shape)
If you have methods that are exactly the same, you can replace the interface with abstract class and implement those (in C++ interface is just an abstract class with nothing implemented)
Most importantly (I'm emphesizing bullet #1) - you'll enjoy the power of polymorphism. If you use enums to declare your types, you'll one day have to change a lot of places in the code if you want to add new shape. Whereas, you won't have to change nothing for a new class the implements shape.
Go through a C++ tutorial for the basics, and read something like Stroustrup's "The C++ programming language" to learn how to use the language idiomatically.
Do not believe people telling you you'd have to learn OOP independent of the language. The dirty secret is that what each language understands as OOP is by no means even vaguely similar in some cases, so having a solid base in, e.g. Java, is not really a big help for C++; it goes so far that the language go just doesn't have classes at all. Besides, C++ is explicitly a multi-paradigm language, including procedural, object oriented, and generic programming in one package. You need to learn how to combine that effectively. It has been designed for maximal performance, which means some of the lower-bit stuff shows through, leaving many performance-related decisions in the hands of the programmer, where other languages just don't give options. C++ has a very extensive library of generic algorithms, learning to use those is required part of the curriculum.
Start small, so in a couple year's time you can chuckle fondly over the naïveté of your first attempts, instead of pulling your hair out.
Don't fret over "efficiency," use virtual member functions everywhere unless there is a compelling reason not to. Get a good grip on references and const. Getting an object design right is very hard, don't expect the first (or fifth) attempt to be the last.
First, a little background on OOP and how C++ and other languages like Java differ.
People tend to use object-oriented programming for several different purposes:
Generic programming: writing code that is generic; i.e. that works on any object or data that provides a specified interface, without needing to care about the implementation details.
Modularity and encapsulation: preventing different pieces of code from becoming too tightly coupled to each other (called "modularity"), by hiding irrelevant implementation details from its users.
It's another way to think about separation of concerns.
Static polymorphism: customizing a "default" implementation of some behavior for a specific class of objects while keeping the code modular, where the set of possible customizations is already known when you are writing your program.
(Note: if you didn't need to keep the code modular, then choosing behavior would be as simple as an if or switch, but then the original code would need to account for all of the possibilities.)
Dynamic polymorphism: like static polymorphism, except the set of possible customizations is not already known -- perhaps because you expect the user of the library to implement the particular behavior later, e.g. to make a plug-in for your program.
In Java, the same tools (inheritance and overriding) are used for solving basically all of these problems.
The upside is that there's only one way to solve all of the problems, so it's easier to learn.
The downside is a sometimes-but-not-always-negligible efficiency penalty: a solution that resolves concern #4 is more costly than one that only needs to resolve #3.
Now, enter C++.
C++ has different tools for dealing with all of these, and even when they use the same tool (such as inheritance) for the same problem, they are used in such different ways that they are effectively completely different solutions than the classic "inherit + override" you see in Java:
Generic programming: C++ templates are made for this. They're similar to Java's generics, but in fact Java's generics often require inheritance to be useful, whereas C++ templates have nothing to do with inheritance in general.
Modularity and encapsulation: C++ classes have public and private access modifiers, just like in Java. In this respect, the two languages are very similar.
Static polymorphism: Java has no way of solving this particular problem, and instead forces you to use a solution for #4, paying a penalty that you don't necessarily need to pay. C++, on the other hand, uses a combination of template classes and inheritance called CRTP to solve this problem. This type of inheritance is very different from the one for #4.
Dynamic polymorphism: C++ and Java both allow for inheritance and function overriding, and are similar in this respect.
Now, back to your question. How would I solve this problem?
It follows from the above discussion that inheritance isn't the single hammer meant for all nails.
Probably the best way (although perhaps the most complicated way) is to use #3 for this task.
If need be, you can implement #4 on top of it for the classes that need it, without affecting other classes.
You declare a class called Shape and define the base functionality:
class Graphics; // Assume already declared
template<class Derived = void>
class Shape; // Declare the shape class
template<>
class Shape<> // Specialize Shape<void> as base functionality
{
Color _color;
public:
// Data and functionality for all shapes goes here
// if it does NOT depend on the particular shape
Color color() const { return this->_color; }
void color(Color value) { this->_color = value; }
};
Then you define the generic functionality:
template<class Derived>
class Shape : public Shape<> // Inherit base functionality
{
public:
// You're not required to actually declare these,
// but do it for the sake of documentation.
// The subclasses are expected to define these.
size_t vertices() const;
Point vertex(size_t vertex_index) const;
void draw_center(Graphics &g) const { g.draw_pixel(shape.center()); }
void draw_outline()
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point p1 = me.vertex(0);
for (size_t i = 1; i < me.vertices(); ++i)
{
Point p2 = me.vertex(1);
g.draw_line(p1, p2);
p1 = p2;
}
}
Point center() const // Uses the methods above from the subclass
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point center = Point();
for (size_t i = 0; i < me.vertices(); ++i)
{ center += (center * i + me.vertex(i)) / (i + 1); }
return center;
}
};
Once you do that, you can define new shapes:
template<>
class Square : public Shape<Square>
{
Point _top_left, _bottom_right;
public:
size_t vertices() const { return 4; }
Point vertex(size_t vertex_index) const
{
switch (vertex_index)
{
case 0: return this->_top_left;
case 1: return Point(this->_bottom_right.x, this->_top_left.y);
case 2: return this->_bottom_right;
case 3: return Point(this->_top_left.x, this->_bottom_right.y);
default: throw std::out_of_range("invalid vertex");
}
}
// No need to define center() -- it is already available!
};
This is probably the best method since you most likely already know all possible shapes at compile-time (i.e. you don't expect the user will write a plug-in to define his own shape), and thus don't need any of the whole deal with virtual. Yet it keeps the code modular and separates the concerns of the different shapes, effectively giving you the same benefits as a dynamic-polymorphism approach.
(It is also the most efficient option at run-time, at the cost of being a bit more complicated at compile-time.)
Hope this helps.
Here is an example of something similar to code I recently wrote, that has proven to be a little contentious at work:
namespace Shape
{
class Renderer
{
public:
virtual void Draw () = 0;
};
};
namespace Square
{
class Renderer : public Shape::Renderer
{
virtual void Draw ();
};
};
namespace Circle
{
class Renderer : public Shape::Renderer
{
virtual void Draw ();
};
};
The important points are:
1) Within the inheritance hierarchy most classes have the same name but belong to different namespaces
2) 'Renderer' would be just one of several inheritance hierarchies within these same namespaces
My question is: might this ever be a reasonable use of namespaces, or is it an abuse of namespaces?
Does anyone else use namespaces in this way?
Having received some comments already, it appears that it may aid the discussion if I point out that in my real-world coding, the namespaces are actually different database technologies, so one is ADO and another is SQLite. Therefore to me the namespaces really are useful groupings.
It is sufficiently different that you need a really strong justification for why you would want to write your code this way. Your co-workers are just looking at the code going "That's really weird," not "That's really weird, but it's really clever because of X." It's not an abuse, it's just unconventional. But without a sufficiently convincing X-factor, unconventional is bad.
In my Opinion, this is a misuse of the namespace concept because you spam the global namespace with sub namespaces.
the purpose of namespaces is to logically group functionality without the need of overlong names and the option for handy usage via using clause (ONLY IN CPP - NEVER IN HEADER).
I would invert the nesting:
namespace Renderer
{
class BasicShape
{
//...
};
class Circle: public BasicShape
{};
class Sqare: public BasicShape
{};
}
I have the following problem in application architecture and am willing to solve it (sorry for a lot of text).
I am building a game engine prototype and I have base abstract class AbstractRenderer (I will use C++ syntax, but still the problem is general).
Assume there are some derived implementations of this renderer, let's say DirectxRenderer and OpenglRenderer.
Now, let's say that only one of these renderers (let's stick to DirectX-based) has a member called IDirect3D9Device* m_device; Obviously at this point everything is fine - m_device is used internally in DirectxRenderer and shouldn't be exposed in the abstract AbstractRenderer superclass.
I also add some abstract rendering interface, for instance IRenderable. It means simply one pure virtual method virtual void Render(AbstractRenderer* renderer) const = 0;
And this is the place where some problems start. Assume I am modelling some scene, so, this scene will probably have some geometrical objects in it.
I create abstract superclass AbstractGeometricalObject and derived DirectX-based implementation DirectxGeometricalObject. The second one would be responsible for storing pointers to DirectX-specific vertex & index buffers.
Now - the problem.
AbstractGeometricalObject should obviously derive the IRenderable interface, because it's renderable in logical terms.
If I derive my DirectxGeometricalObject from AbstractGeometricalObject, the first one should have virtual void Render(AbstractRenderer* renderer) const { ... } method in it, and that Abstract... stuff brings some troubles.
See the code for better explanation:
And for now my classes look the following way:
class AbstractGeometricalObject : public IRenderable {
virtual void Render(AbstractRenderer* renderer) const { ... }
};
class DirectxGeometricalObject : public AbstractGeometricalObject {
virtual void Render(AbstractRenderer* renderer) const {
// I think it's ok to assume that in 99 / 100 cases the renderer
// would be a valid DirectxRenderer object
// Assume that rendering a DirectxGeometricalObject requires
// the renderer to be a DirectxRenderer, but not an AbstractRenderer
// (it could utilize some DX-specific settings, class members, etc
// This means that I would have to ***downcast*** here and this seems really
// bad to me, because it means that this architecture sucks
renderer = dynamic_cast<DirectxRenderer*>(renderer);
// Use the DirectX capabilities, that's can't be taken out
// to the AbstractRenderer superclass
renderer.DirectxSpecificFoo(...);
}
I know I'm probably worrying too much, but this downcast in such a simple case means that I could be forced to make lots of downcasts if my application grows.
Definitely, I would like to avoid this, so please, could you advice me something better in design terms / point out my errors.
Thank you
This might be a situation where the template pattern (not to be confused with C++ templates) comes in handy. The public Render in the abstract class should be non-virtual, but have it call a private virtual function (e.g. DoRender). Then in the derived classes, you override DoRender instead.
Here's an article that goes into great depth describing the use of template pattern with private virtual functions.
Edit:
I started to put together an example of what I meant, and it seems like there's actually a broader flaw in the architecture. Your use of AbstractRenderer is somewhat frivolous since you're forcing each geometricalobject to be intimately aware of a particular renderer type.
Either the renderer should be able to work off the public methods of Renderables, or Renderables should be able to work off the public methods of the Renderer. Or perhaps you can give the concrete renderers a Renderable factory if there really needs to be such an intimate connection. I'm sure there are some other patterns that would fit well, too.
I don't see what your code wants to achieve. You derive Renderable objects to DirectXRenderables and OpenGLRenderables and then provide OpenGL or DirectX functionality in something derived from Renderer. A specific thing uses another specific thing so to speak.
It would seem much more reasonable to identify general rendering functions, make them pure virtual members of your abstract renderer and implement them in DirectXRenderer and OpenGLRenderer. Then a IRenderable would have a member function draw roughly like this:
void draw(const AbstractRenderer& r) {
//general stuff
r.drawLine(...);
//only possible on directX
if(DirectxRenderer rx = dynamic_cast<DirectxRenderer*>(r)) {
//...
} else {
//throw exception or do fallback rendering in case we use something else
}
}
Using templates, you could split the IRendable into two classes, one for each of the two renderer types. This is probably not the best answer, but it does avoid the need for the dynamic cast:
template <typename RendererType>
struct IRenderable {
virtual void Render(RendererType* renderer) const = 0;
}
template <typename RendererType>
class AbstractGeometricalObject : public IRenderable<RendererType> {
virtual void Render(RendererType* renderer) const { ... }
};
class DirectxGeometricalObject : public AbstractGeometricalObject<DirectxRenderer> {
// this class will now require a void Render(DirectxRenderer* renderer)
}
Use a setter to set the renderer var and cast it to the proper type in that one place.
See if the Bridge design pattern helps you: "Decouple an abstraction from its implementation so that the two can vary independently." In your example, AbstractGeometricalObject would point to an implementation, a pure virtual interface with platform-specific subclasses. The tricky part is taking the time to discover that interface.
Let's distance from compilers and consider theory. If DirectxGeometricalObject::Render expects DirectxRenderer as parameter and not any AbstractRenderer, then some other OtherGeometricalObject::Render will probably expect OtherRenderer object as parameter.
So, different implementations of AbstractGeometricalObject have different signatures of their Render methods. If they are different, then there is no purpose in defining the virtual AbstractGeometricalObject::Render.
If you declare AbstractGeometricalObject::Render(AbstractRenderer*), then you should be able to pass any renderer to any geometrical object. In your case, you can't because dynamic_cast would fail.
Here is my code:
class Soldier {
public:
Soldier(const string &name, const Gun &gun);
string getName();
private:
Gun gun;
string name;
};
class Gun {
public:
void fire();
void load(int bullets);
int getBullets();
private:
int bullets;
}
I need to call all the member functions of Gun over a Soldier object. Something like:
soldier.gun.fire();
or
soldier.getGun().load(15);
So which one is a better design? Hiding the gun object as a private member and access it with getGun() function. Or making it a public member? Or I can encapsulate all these functions would make the implementation harder:
soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
So which one do you think is the best?
I would say go with your second option:
soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
Initially it's more work, but as the system gets more complex, you may find that a soldier will want to do other things before and after firing their gun (maybe check if they have enough ammo and then scream "Die suckers!!" before firing, and mutter "that's gotta hurt" after, and check to see if they need a reload). It also hides from the users of the Soldier class the unnecessary details of how exactly the gun is being fired.
First off, you'd be violating the Law of Demeter by accessing the Gun from outside the Soldier class.
I would consider methods like these instead:
soldier.ArmWeapon(...);
soldier.Attack(...);
This way you could also implement your fist, knife, grenade, baseball bat, laser cat, etc.
The Law of Demeter would say to encapsulate the functions.
http://en.wikipedia.org/wiki/Law_of_Demeter
This way, if you want some type of interaction between the soldier and the gun, you have a space to insert the code.
Edit: Found the relevant article from the Wikipedia link:
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
The paperboy example is very, very similar to the soldier example you post.
Indeed, it depends a lot about how much control you want to have.
To model the real world, you might even want to completely encapsulate the gun object, and just have a soldier.attack() method. The soldier.attack() method would then see whether the soldier was carrying a gun, and what the state of the gun was, and fire or reload it as necessary. Or possibly throw the gun at the target and run away, if insufficient ammunition were present for either operation...
If you expose gun, you allow things beyond the member functions of the Gun, which is probably not a good idea:
soldier.gun = anotherGun; // where did you drop your old gun?
If you use getGun(), the calls look a little ugly, but you can add functions to Gun without modifying Soldier.
If you encapsulate the functions (which I recommend) you can modify the Gun or introduce other (derived) classes of Gun without changing the interface to Soldier.
Usually my decision is based on the nature of the container class (in this case, Soldier). Either it is entirely a POD or is not. If it's not a POD, I make all data members private and provide accessor methods. The class is a POD only if it has no invariants (i.e. there is no way an external actor can make its state inconsistent by modifying its members). Your soldier class looks more like a non-POD to me, so I would go to the accessor method option. If it would return a const reference or a regular reference is your own decision, based on the behaviour of fire() and the other methods (if they modify gun's state or not).
BTW, Bjarne Stroustrup talks a little about this issue in his site:
http://www.artima.com/intv/goldilocks3.html
A sidenote: I know that's not precisely what you asked, but I'd advice you to also consider the many mentions made in other answers to the law of Demeter: to expose action methods (that act on gun) instead of the entire gun object via a getter method. Since the soldier "has" the gun (it is in his hand and he pulls the trigger), it seems more natural to me that the other actors "ask" the soldier to fire. I know this may be tedious if gun has many methods to act on, but maybe also these could be grouped in more high-level actions that the soldier exposes.
Provide a "getGun()" or simply "gun()".
Imagine one day you may need to make that method more complex:
Gun* getGun() {
if (!out_of_bullets_) {
return &gun_;
} else {
PullPieceFromAnkle();
return &secret_gun_;
}
}
Also, you may want to provide a const accessor so people can use a const gun on a const soldier:
const Gun &getGun() const { return gun_; }
There's no golden rule that applies 100% of the time. It's really a judgement call depending on your needs.
It depends on how much functionality you want to hide/disallow for the gun from access to the Solider.
If you want to have only read only access to the Gun you could return a const reference to your own member.
If you want to expose only certain functionality you could make wrapper functions. If you don't want the user to try to change Gun settings through the Soldier then make wrapper functions.
Generally though, I see the Gun as it's own object and if you don't mind exposing all of Gun's functionality, and don't mind allow things to be changed through the Soldier object, just make it public.
You probably don't want a copy the gun so if you make a GetGun() method make sure that you aren't returning a copy of the gun.
If you want to keep your code simple then have the soldier responsible for dealing with the gun. Does your other code need to work with the gun directly? Or can a soldier always know how to work/reload his own gun?
Encapsulate the functions to provide a consistent UI even if you later change the logic. Naming conventions are up to you, but I normally don't use "getFoo()", but just "foo()" as accessors and "setFoo()" as setters.
return reference-to-const when you can (Effective C++ Item #3).
Prefer consts, enums, and inlines to using hard coded numbers (Item #4)
provide unique naming conventions for your private members to distinguish them from arguments
Use unsigned values where they make sense to move errors to compile time
When const values, like maximums, apply to an entire class. Make them static.
If you plan to inherit, make sure your destructors are virtual
initialize all members to sane defaults
This is how the classes look after that. CodePad
#include <iostream>
#include <string>
#include <stdint.h>
using namespace std;
class Gun
{
public:
Gun() : _bullets(0) {}
virtual ~Gun() {}
void fire() {cout << "bang bang" << endl; _bullets--;}
void load(const uint16_t bullets) {_bullets = bullets;}
const int bullets() const {return _bullets;}
static const uint16_t MAX_BULLETS = 17;
protected:
int _bullets;
};
class Soldier
{
public:
Soldier(const string &name, const Gun &gun) : _name(name), _gun(gun) {}
virtual ~Soldier() {}
const string& name() const;
Gun& gun() {return _gun;}
protected:
string _name;
Gun _gun;
};
int main (int argc, char const *argv[])
{
Gun gun; // initialize
string name("Foo");
Soldier soldier(name, gun);
soldier.gun().load(Gun::MAX_BULLETS);
for(size_t i = 0; i < Gun::MAX_BULLETS; ++i)
{
soldier.gun().fire();
cout << "I have " << soldier.gun().bullets() << " left!" << endl;
}
return 0;
}
struct InkPen
{
void Write()
{
this->WriteImplementation();
}
void WriteImplementation()
{
std::cout << "Writing using a inkpen" << std::endl;
}
};
struct BoldPen
{
void Write()
{
std::cout << "Writing using a boldpen" << std::endl;
}
};
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
int main()
{
Writer<InkPen> writer;
writer.StartWriting();
Writer<BoldPen> writer1;
writer1.StartWriting();
return 0;
}
I wrote the above code as part of learning policy based designs. I have few questions on the above code
1 - Does this implementation look correct? I mean: does it really look like a policy based design?
2 - I can now hook any kind of pens to writer. But what will I do when I got a pen with no default constructor (only parameterized constructors)? How will I handle this situation?
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
3 - When the above code is used like
Writer<InkPen> writer;
I guess compiler will replace PenType with InkPen. If yes, why I am not able to call just Write() from StartWriting() instead of prefixing base class name (PenType::Write())?
4 - I think policy based design forces you to derive from classes which is semantically invalid. In the above code, a writer is derived from a pen only because writer uses a pen. But saying writer is a pen is semantically invalid. Is there any other better way to address this or I am missing something here?
Any thoughts?
Here's how I would implement the class:
template<class PenType>
class Writer
{
public:
Writer(const PenType& pen = PenType()) : pen(pen) {}
void StartWriting()
{
pen.Write();
}
private:
PenType pen;
};
This allows the user to pass a specific Pen object to the constructor, if it either doesn't have a default constructor, or you don't want it to be used, and second, it still allows you to omit the PenType object if you're happy to let it create one with the default constructor. The C++ standard library does the same in many classes (think of the allocators for container classes for example).
I removed the inheritance. It didn't really seem to add anything (and might cause problems. You probably don't want the user of the Writer class to call the PenType::Write function directly. You could use private inheritance instead, but often, composition is a simpler and more conventional design.
In general, policy-based design does not require inheritance. Adding it as a member works just as well. If you do go for inheritance, make it private so you don't get the problem you mentioned as #4.
This looks like a nice example of policy-based smart pointer implementation: link. Andrei Alexandrescu describes policy-based smart pointer implementation in one of his books. As to your questions now. I have some experience in this stuff but not enough to take my words for granted:
Ad 1 & 4. I guess policy-based design is more about templates than inheritance. You write a template class and template arguments are policy classes, like that:
template<class FooPolicy, class BarPolicy>
class Baz {
// implementation goes here
};
Then you use methods from policy classes in your class:
void Baz::someMethod(int someArg) {
FooPolicy::methodInit();
// some stuff
BarPolicy::methodDone();
}
I use static methods in this example because often policy doesn't require any state. If it does, you incorporate policy's state by composition, not by inheritance:
template<class FooPolicy, class BarPolicy>
class Baz {
private:
FooPolicy::State fooState; // might require 'typename' keyword, I didn't
// actually tried this in any compiler
// rest of the Baz class
};
Ad 2. You can write a template specialization - for a particular combination of main class and it's policies you can write a special version of any method or constructor, AFAIK:
template <>
Baz<SomeConcreteFooPolicy, SomeConcreteBazPolicy>::Baz(someArgument)
: fooState(someArgument)
{
// stuff here
}
Hope it helps you a bit,
Mike
I know this thread is old, but there is a major flaw in the initial post and this thread is one of the top results of Google...so:
Do not use public inheritance for policy-based design! This would say "is-a" instead of "has-a" / "uses-a". You should therefore use private inheritance!
1 - Is this implementation looks
correct? I mean is it really looks
like a policy based design?
Policy classes derive their usefulness from combining behaviors to produce a rich variety of combinations. When you have a single template parameter like this, it's not much of a policy class.
2 - I can now hook any kind of pens to
writer. But what will I do when I got
a pen with no default constructor
(only parameterized constructors)? How
will I handle this situation?
Again, this is an odd example of a policy class. However, to directly answer your question, you can provide a constructor which accepts PenType. You should probably also avoid inheriting from PenType and store it as a member instead (no need to tightly couple your policy class with its policies).
I guess compiler will replace PenType
with InkPen. If yes, why I am not able
to call just Write() from
StartWriting() instead of prefixing
base class name (PenType::Write())?
When you inherit from a class template, you have to specify this->member or BaseClass::member.
4 - I think policy based design forces
you to derive from classes which is
semantically invalid. In the above
code, a writer is derived from a pen
only because writer uses a pen. But
saying writer is a pen is semantically
invalid. Is there any other better way
to address this or I am missing
something here?
Store PenType as a member as suggested above. Always prefer composition to inheritance as it avoids the tight coupling relationship of inheritance.