c++ composition (has-a) issue - c++

One important and essential rule I have learnt as a C++ programmer is the preference of Composition over Inheritance (http://en.wikipedia.org/wiki/Composition_over_inheritance).
I totally agree with this rule which mostly makes things much more simple than It would be if we used Inheritance.
I have a problem which should be solved using Composition but I'm really struggling to do so.
Suppose you have a Vendor Machine, and you have two types of products:
Discrete product - like a snack.
Fluid product - like a drink.
These two types of products will need to be represented in a class called VendorCell which contains the cell content.
These two products share some identical attributes(dm) as Price, Quantity and so on...BUT also contain some different attributes.
Therefore using Composition here might lead for the following result:
class VendorCell {
private : // default access modifier
int price;
int quantity;
// int firstProductAttributeOnly
// char secondProductAttributeOnly
};
As you can see the commented lines show that for a single VendorCell depending on the product it containing, only one of these two commented lines will be significant and useable (the other one is only relevant for the other type - fluid for example).
Therefore I might have a VendorCell with a snack inside and its secondProductAttributeOnly is not needed.
Is composition (for the VendorCell) is the right solution? is It seems proper to you guys that someone will determine the VendorCell type via a constructor and one DM (the DM dedicated for the other type) will not be used at all (mark it as -1 for example) ?>
Thanks you all!

Your general rule of favoring composition over inheritance is right. The problem here is that you want a container of polymorphic objects, not a giant aggregate class that can hold all possible products. However, because of the slicing problem, you can't hold polymorphic objects directly, but you need to hold them by (preferably smart) pointer. You can hold them directly by (smart) pointer such as
class AbstractProduct { /* price, quauntity interface */ };
class AbstractSnack: public AbstractProduct { /* extended interface */ };
class AbstractDrink: public AbstractProduct { /* extended interface */ };
typedef std::unique_ptr<AbstractProduct> VendorCell;
typedef std::vector< VendorCell > VendorMachine;
You simply define your snacks/drinks by deriving from AbstractSnack/AbstractDrink
class SnickersBar: public AbstractSnack { /* your implementation */ };
class CocaColaBottle: public AbstractDrink { /* your implementation */ };
and then you can insert or extract products like this:
// fill the machine
VendorMachine my_machine;
my_machine.emplace_back(new SnickersBar());
my_machine.emplace_back(new CocaColaBottle());
my_snack = my_machine[0]; // get a Snickers bar
my_drink = my_machine[1]; // get a Coca Cola bottle;
There are also other solutions such as Boost.Any that uses a wrapper class that internally holds a pointer to a polymorphic object. You could also refactor this code by replacing the typedef with a separate class VendorMachine that holds a std::vector< VendorCell >, so that you can get a nicer interface (with money exchange functionality e.g.)

You inherit in order to be re-used.
You compose in order to re-use.
If you have different attributes then you probably want to inherit, otherwise compose.
Some variation:
class ProductVariety {
public:
virtual void display(Screen& screen) = 0;
};
An implementation:
class Liquid : public ProductVariety {
public:
virtual void display(Screen& screen) {
//...
}
}
Composing variation:
class Product
{
int price;
int quantity;
unique_ptr<ProductVariety> variety;
}

Related

How to create structs that all implement a trait that have common data members? [duplicate]

I'm trying to implement the Rust equivalent code of the following C++ code which makes use of inheritance, but got stuck. This is my sample code:
class Vehicle {
public:
double lat;
double lon;
double alt;
double speed;
};
class CabVehicle : public Vehicle {
};
class PackerMoverVehicle : public Vehicle {
};
int main() {
CabVehicle cv;
cv.lat = 12.34;
cv.lon = 12.34;
cv.alt = 12.34;
PackerMoverVehicle pmv;
pmv.lat = 12.34;
pmv.lon = 12.34;
pmv.alt = 12.34;
}
How should this be written in Rust?
The general answer is to use composition instead of inheritance. Depending on the application, there can be different ways the composition should go. In most cases, you should start with
struct VehicleState {
lat: f64,
lon: f64,
alt: f64,
speed: f64,
}
The remaining question then is how your different types of vehicles are going to be used.
Way 1: If different parts of the code use the different types of vehicles in distinct, non-overlapping ways, you might simply contain the state struct in the specific structs:
struct Cab {
state: VehicleState,
// ... other fields
}
struct PackerMover {
state: VehicleState,
// ... other fields
}
This is the version most directly analogous to C++ inheritance, particularly in memory layout and in static typing. However, this makes it awkward to access the common state for different vehicles, and it does not support dynamic dispatch, unless you write a trait with a method to access state (which comes with some limitations in the kinds of code you can write). You should generally avoid this approach unless you know you don't need anything else.
Way 2: If there is code which should be generic over which kind of vehicle is in use, but this is statically decided, you might make a generic struct:
struct Vehicle<T> {
state: VehicleState,
details: T,
}
struct Cab { /* ... */ }
struct PackerMover { /* ... */ }
/// This function only works with Cabs
fn foo(vehicle: Vehicle<Cab>) { /* ... */ }
/// This function works with any Vehicle
fn foo<T>(vehicle: Vehicle<T>) { /* ... */ }
This makes it easy to access the state, and all usage is statically dispatched.
It can be dynamically dispatched too if you make one small change to Vehicle and add a trait:
struct Vehicle<T: ?Sized> { /* ... */
// ^^^^^^^^ remove default restriction on the type parameter
trait VehicleDetails { /* add methods here */ }
impl VehicleDetails for Cab { /* ... */ }
impl VehicleDetails for PackerMover { /* ... */ }
This allows you to coerce a reference (or pointer or Box too) &Vehicle<Cab> into &Vehicle<dyn VehicleDetails>, which is a type that a pointer to any Vehicle whose T implements VehicleDetails. This can be used to put a variety of vehicles in a Vec<Box<Vehicle<dyn VehicleDetails>>>, for example. Using dyn causes dispatch through vtables, like C++ virtual methods.
(Info on this language feature. The documentation says that “custom DSTs are a largely half-baked feature for now” but this particular case is exactly the case where they do work without any trouble.)
This is not a good choice if you want to be able to find out which “subclass” is being used and interact with it specifically; it is a good choice if all particular characteristics of the vehicle can be expressed within the VehicleDetails trait.
Way 3: If the application is going to be routinely working with dynamically-chosen vehicle types — especially if it frequently wants to ask the question “is this vehicle a Cab” and then interact with its Cabness — then you should probably use an enum to contain the details.
struct Vehicle {
state: VehicleState,
kind: VehicleKind,
}
enum VehicleKind {
Cab {
seats: u16,
},
PackerMover {
cargo_capacity: u64,
}
}
This is dynamically dispatched in the sense that every Vehicle can be any kind, so you can always mix-and-match vehicle kinds, but without involving any pointers or vtables. The main disadvantage is that extending it to new kinds requires modifying the single enum VehicleKind, so this is not suitable for a library whose users would be writing subclasses in C++. However, this is a lot less fiddly to work with than the Vehicle<dyn VehicleDetails> I mentioned above.
Rust is basically more like a procedural and a functional language with some pseudo-OO features, it’s simultaneously lower-level and more abstract than C++ (closer to C or even to C—, but with ZCA and stronger typing). The answer is: there’s no inheritance in Rust, use composition or just rewrite the whole structure. This may look wild for you, but after some time you will understand that there’s no need in inheritance.

Handling derived class creation using mappers in C++

I'm reading through Martin Fowler's PoEAA right now on object-relational structural patterns. As a project to do while learning them, I thought I'd build a mini eCommerce system in C++. I'm having trouble figuring out how to return the objects from the mapper.
I have a Product base class, which has derived classes Hat and Shirt. Products have a type member to identify which derived class they are. I also have a ProductMapper class, with derived classes HatMapper and ShirtMapper, all of which implement a bunch of finder methods which let me try and retrieve certain hats and shirts.
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
};
// Derived classes don't necessarily have the same members.
class Hat : public Product
{
unsigned char fitted;
unsigned char color;
unsigned char style;
};
class Shirt : public Product
{
unsigned char size;
};
In the logic part of my application where I'd instantiate these mappers and retrieve products is where I'm having trouble. I can instantiate a HatMapper and pull back Hat objects without any problem, same with a ShirtMapper and Shirt objects. The patterns work great in these cases (in particular I'm using class table inheritance, i.e. one product table with product data, one table for hats with hat-specific data, and one table for shirts with shirt-specific data).
My problem is, what do I do if I want to retrieve all products, both hats and shirts? I can instantiate a ProductMapper and fetch all of the product data, but that seems like the wrong approach since I'd have to loop through all the Products I retrieve and build up Hats and Shirts based on their type in my logic portion of the program. Additionally, I'd have to modify any code that handles the situation this way when I add new product types. Seems bad.
The Fowler book has examples of the mappers with the base mapper using the derived mappers which seems completely wrong to me (have to modify the base mapper every time I add a new product, not great). Here's a quick example of how it's done there:
class ProductMapper
{
unsigned long long int productId;
unsigned long long int productType;
HatMapper * hm;
ShirtMapper * sm;
Product * FindById(unsigned long long int id)
{
// Query database for data.
if (this->productType == PRODUCT_TYPE_HAT)
{
return hm->FindById(id); // Hat object.
}
else if (this->productType == PRODUCT_TYPE_SHIRT)
{
return sm->FindById(id); // Shirt object.
}
return NULL;
}
};
Here's how I'd use this in the logic part of my program. Examples of this aren't provided in the book:
ProductMapper * pm = new ProductMapper();
Product * p = pm->FindById(1); // It's a Product, but a Hat or Shirt?
// Have to check type since a Product was returned.
switch (p->type)
{
case PRODUCT_TYPE_HAT:
{
Hat * h = (Hat) p;
break;
}
// Etc. Modify this every time a new product type is added or removed.
}
This will introduce circular dependencies. Additionally, assuming I somehow eliminate the circular dependencies, the result of the HatMapper and ShirtMapper classes are Hat objects and Shirt objects. Thus when I return from the ProductMapper, I'll be downcasting, so I'd have to again manipulate the result in my logic, which again introduces the issue of modifying code when I introduce new product types.
I'm at a loss for what to do. In a perfect world, I'd like to have a Product class and a ProductMapper class, both of which I can extend quickly, introducing new product types without having to modify existing code (at least too much).
I would like to be able to use these patterns from PoEAA, they do seem nice and useful, but I'm not sure if it's just something I can't do in C++ or I'm missing something that's preventing me from doing it. Alternative patterns and approaches are also really welcomed.
It feels like the Type Object pattern could help in this case, I know the link is about game programming but it is sufficient to apply the pattern to other domains.
The problem right now is that if you want to add products you have to add several classes, which can become hard to maintain as you noticed.
Edit: Maybe you could use something like that (code is C++11 to simplify the example):
class ProductProperty
{
typedef std::map<std::string, unsigned char> PropertyMap;
PropertyMap properties;
public:
ProductProperty(std::initializer_list<PropertyMap::value_type> il):
properties(il)
{}
// Use of at() is intended to only deal with the defined properties
const PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop) const
{
return properties.at(prop);
}
PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop)
{
return properties.at(prop);
}
};
// Some helpers to illustrate
std::shared_ptr<ProductProperty> makeHatProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{
{"fitted", ***whatever**},
{"color", ***whatever**},
{"style", ***whatever**}
});
}
std::shared_ptr<ProductProperty> makeShirtProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{{"size", ***whatever**}}
);
}
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
std::shared_ptr<ProductProperty> properties;
public:
Product(std::shared_ptr<ProductProperty> props):
properties(props)
{}
// Whatever function you need to get/set/check properties
};

C++ data structure design: children with different fields and function

I just started learning C++ and I'm used to Java paradigms, so I'm not sure how this should be done:
I need to represent a vector of products of two different types: packaged and fresh food. They have some common fields with a single implementation (availability, re-stock quantity etc), but they have also different fields and functions with different return types.
I.E: fresh foods may have a boolean field needsRefrigeration, other
products may have an integer representing a category (food, cleaning,
bricolage, forniture...).
In Java I would create a Product object with the common fields and a PackagedProduct (extending Product) plus a FreshProduct (also extending Product) with their particular fields. Then I'd place every product in a vector and accessed as Product when I need the common fields, safely-casted (with instanceof) to the right class when I need to access the child's fields.
I know this is not the right way in C++ and I don't want to force java programming paradigms to C++.
I can imagine:
create all the functions required by all the cildren as virtual in the parent and add a field in the parent representing the type of the cild, so it can safely casted
create a wrapper object containing two different vectors, each one of the type of a child object and return the values in the correct order, eventually using a third int vector.
I think these solutions are really bad, and I'm almost sure there must be a better way, but I can't imagine it. Can you help me?
What's the right way to do this?
I need to represent a vector of products of two different types: packaged and fresh food.
Do you really need both types of product in the same vector? Can't you have two vectors?
std::vector<PackagedProduct> packaged;
std::vector<FreshProduct> fresh;
packaged.emplace_back(1, 2, 3);
fresh.emplace_back(4, 5, 6);
This will be by far the most efficient solution. (Less indirections keep the prefetcher happy.)
If you absolutely need both kinds of products in the same vector, you must use indirection:
std::vector<std::unique_ptr<Product>> products;
products.push_back(std::make_unique<PackagedProduct>(1, 2, 3));
products.push_back(std::make_unique<FreshProduct>(4, 5, 6));
Instead of checking the dynamic type at runtime and downcast, you should read up on virtual methods.
The basic idea is the same as in Java: Use inheritance to create a class hierarchy:
class Product { public: virtual ~Product(); ... };
class PackagedProduct : public Product { ... };
class FreshProduct : public Product { ... };
In Java, the vector (or list, container, ...) stores by-reference, not by-value. That's the crucial difference. In C++, this means using a smart pointer:
std::vector< std::shared_ptr< Product > > v;
v.push_back( std::make_shared< FreshProduct >( some args... ) );
You can use dynamic_pointer_cast once you retrieved the pointer back from the vector to check what object it is, but other options are available.
This is, of course, just a rough idea and you'll need to learn a lot about the details, shared_ptr, etc. but I hope you have enough keywords and ideas to google now :)
Create a Product object with the common fields and a PackagedProduct (extending Product) plus a FreshProduct (also extending Product) with their particular fields. Then store smart pointers to them in:
std::vector<std::unique_ptr<Product> > Vec;
If FredOverflow's suggestion of using two vectors doesn't suit your needs, an alternative could be to make a variant of the two types and keep a vector of variants. This is fairly easy to do using boost::variant. You can wrap the functionality you need in free functions or you can wrap the variant in a class. Here's an example
#include <boost/variant/variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
struct FreshProduct
{
double price;
bool needsRefrigeration;
};
struct PackagedProduct
{
double price;
};
struct VariantProduct
{
VariantProduct(const FreshProduct& p) : product(p) {}
VariantProduct(const PackagedProduct& p) : product(p) {}
double getPrice() const;
bool needsRefrigeration() const
{
struct helper : public boost::static_visitor<bool>
{
bool operator ()(const FreshProduct& product) const
{
return product.needsRefrigeration;
}
bool operator ()(...) const
{
return false;
}
};
return boost::apply_visitor(helper(), product);
}
private:
boost::variant<FreshProduct, PackagedProduct> product;
};
// in cpp
namespace {
struct GetPrice : public boost::static_visitor<double>
{
template <class T>
double operator ()(const T& product) const
{
return product.price;
}
};
} // anonymous namespace
double VariantProduct::getPrice() const
{
return boost::apply_visitor(GetPrice(), product);
}
The advantage of this approach is that you don't need to use dynamic allocation in order to keep a collection of fresh or packaged products. The downside is that it is not so easy to extend the types supported in the variant as when using inheritance.

Creating classes to represent different permutations of a type

Suppose I have a class structure like (simplifying the actual classes I have):
class Graph
{
};
class DerivedGraph : public Graph
{
};
class DerivedGraph2 : public Graph
{
};
I want to expand this structure to account for different variations of the same graph. Ideally I would like to be able to do something like:
class Graph
{
};
// Removed
//class DerivedGraph : public Graph
//{
//};
// Removed
//class DerivedGraph2 : public Graph
//{
//};
class DerivedGraph3 : public Graph // really just a mode of DerivedGraph
{
};
class DerivedGraph4 : public Graph // really just a second mode of DerivedGraph
{
};
class DerivedGraph5 : public Graph // really just a mode of DerivedGraph2
{
};
class DerivedGraph6 : public Graph // really just a second mode of DerivedGraph2
{
};
But you can quickly see the problem here -- I am having to create too many classes here. Also, the base class is extremely complex and large (the bottom line is that it just plain sucks) ... so I don't want to make too many structural changes. I want the flexibility of defining things at the level of just the graph itself but at the same time have the flexibility of defining things for a particular mode of one graph type. I would like to be able to use virtual functions such as DoesGraphSupportNormalizedData() or something like that (this is just a simple example). Each class would then override this method.
Another idea I had was to create a separate class structure for the modes themselves (the Graph class would create an instance of it), like:
class BaseMode
{
};
class Mode1 : public BaseMode
{
};
class Mode2 : public BaseMode
{
};
Now the problem is that these mode classes need access to several pieces of data from the Graph class ... and I really don't want to pass all of that information. The mode class would then become just as useless and wouldn't be flexible at all. I just can't think of a clean way to deal with this. The best I could come up with is to have the mode classes do what it can without having to pass all kinds of crap to it but now the interface is just goofy and awkward. Any ideas?
You can either user and interface or use inherited classes from what I can gather from your description.
If you use a base-class and inherit off of it just have the things you don't want derived classes to have just give them the private access modifier and then protected or public for the others (depending on the situation of course). That way your derived classes only take what information they need. You could also have a instance variable that needs to be set in each of lower classes to define things about each derived class. Access modifiers are your friends.
If you use an interface just include everything each graph will need and then when building the individual classes just customize them from there to include the specialties.
If it were up to me, personally, I would go with inheritance over an interface but that's just me.
I ran in this kind of a problem before (and still now and then...)
In this case, you may be taking it the wrong way, what you're looking into is device a specialized function depending on the type of graph and mode. Inheritance is nice, but it has its limits as you mentioned. Especially because the user may want to switch the type of graph, but keep is existing graph object. Inheritance is not helpful in that case.
One way to do something like this is to create functions that get called depending on the current type and mode. Say you have to draw lines and the mode can be set to LINE or DOTS. You could have two functions that draw a line and are specific to a mode or another:
void Graph::draw_line_line(line l)
{
// draw a line
}
void Graph::draw_line_dots(line l)
{
// draw a dots along the line
}
Now you can define a type which represents that type of render functions and a variable member for it:
typedef void (Graph::*draw_line_func)(line l);
draw_line_func m_draw_line;
With that in hands, you can program your set_mode() function, something like this:
void Graph::set_mode(mode_t mode)
{
m_mode = mode; // save for get_mode() to work
switch(mode)
{
case LINE:
m_draw_line = &Draw::draw_line_line;
break;
case DOTS:
m_draw_line = &Draw::draw_line_dots;
break;
...
}
}
Now when you want to render the line, you do call this specialized function and you do not need to know whether it is a LINE or a DOTS...
void Graph::draw_line(line l)
{
this->*m_draw_line(l);
}
This way you create an indirection and make it a lot cleaner in the existing large functions that have large switch or many if() statements without breaking up the existing "powerful" class in many pieces that may become hard to use (because if it's that big it's probably already in use...)

Pattern for storing multiple types of struct in a C++ std::<vector> container

I have a data structure which represents a train, which can be made up of many types of car, for example the train engines, a grain car, a passenger car, and so on:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
}
std::vector<TrainCar*> cars;
cars.push_back(new TrainCar(...));
cars.push_back(new TrainCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
An algorithm will iterate through the cars in the train, and decide how to route/shunt each car (whether to keep it in the train, move it to another point in the train, remove it from the train). This code looks like:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
PowerCar *pc = dynamic_cast<PowerCar*>(*it);
CargoCar *cc = dynamic_cast<CargoCar*>(*it);
if (pc) {
// Apply some PowerCar routing specific logic here
if (start_of_train) {
// Add to some other data structure
}
else if (end_of_train && previous_car_is_also_a_powercar) {
// Add to some other data structure, remove from another one, check if something else...
}
else {
// ...
}
}
else if (cc) {
// Apply some CargoCar routing specific logic here
// Many business logic cases here
}
}
I am unsure whether this pattern (with the dynamic_casts, and chain of if statements) is the best way to process the list of simple structs of varying types. The use of dynamic_cast seems incorrect.
One option would be to move the routing logic to the structs (so like (*it)->route(is_start_of_car, &some_other_data_structure...)), however I'd like to keep the routing logic together if possible.
Is there a better way of iterating through different types of simple struct (with no methods)?, or do I keep the dynamic_cast approach?
The standard solution to this is called double-dispatch. Basically, you first wrap your algorithms in separate functions that are overloaded for each type of car:
void routeCar(PowerCar *);
void routeCar(CargoCar *);
Then, you add a route method to car that is pure virtual in the base-class, and implemented in each of the subclasses:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
virtual void route() = 0;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
virtual void route() {
routeCar(this);
}
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
virtual void route() {
routeCar(this);
}
}
Your loop then looks like this:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
(*it)->route();
}
If you want to choose between different routing-algorithms at run-time, you can wrap the routeCar-functions in an abstract base class and provide different implementations for that. You would then pass the appropriate instance of that class to TrainCar::route.
If the number of classes is manageable, you can give a try to boost::variant.
Using "sum types" in C++ is sometimes a mess, so it is either this or double dispatching.
The classical OO solution would be to make all of the relevant functions
virtual in the base class TrainCar, and put the concrete logic in each
class. You say, however, that you'd like to keep the routing logic
together if possible. There are cases where this is justified, and the
classical solution in such cases is a variant union (boost::variant,
for example). It's up to you to decide which is better in your case.
Compromises are possible as well. For example, one can easily imagine a
case where the routing logic is somewhat independent of the car type
(and you don't want to duplicate it in each car type), but it does
depend on a certain number of characteristics of the car type. In this
case, the virtual function in TrainCar could simply return an object
with the necessary dependent information, to be used by the routing
algorithm. This solution has the advantage of reducing the coupling
between the routing and TrainCar to the minimum necessary.
Depending on the nature of this information, and how it is
used, the returned object could be polymorphic, with it's inheritance
hierarchy reflecting that of TrainCar; in this case, it must be
allocated dynamically, and managed: std::auto_ptr was designed with
exactly this idiom in mind.