A Car case

T

Tim

Dear All,

For the car case I posted before (car has some parts, and parts must
have the same maker, such as Ford), what I really concerned is that:

There are two implementations:

1.

class Car
{
public:
SetEngine(Engine*);
SetTransmission(Transmission*)
private:
Engine *m_engine;
Transmission *m_transmission;
...
};

For a Ford car

Car fordCar;
FordEngine * pFordEngine;
FordTranismission *pFordTransmission;
fordCar.SetEngine(pFordEngine);
fordCar.SetTransmission(pFordTransmission);


2.

class Car
{
public:
virtual SetEngine(Engine*);
virtual SetTransmission(Transmission*)
};

class FordCar : public Car
{
public:
virtual SetEngine(Engine*) {...}
virtual SetTransmission(Transmission*) {...}
private:
FordEngine *m_engine;
FordTransmission *m_transmission;
};

The difference is that I put the private part members is the derived
classes. I want to know which design is better and why?

I appreciate your kind help

Tim
 
H

hbrt

Hi, Tim!
I would rather do this in following way:
1. class Car should have two virtual public (as in your 2. solution)
2. class Car should have two handlers for Engine and Transmission -
but in PROTECTED section
3. class FordCar, derived from Car, should have overloaded functions
from its ancestor
Pros of this solution:
- you cannot create just a 'car' - it has to be FordCar, OpelCar,
FiatCar etc.
- protected section allows you to use both handlers in derived classes
- if you ever try to create a class hierarchy for Engine or/and
Transmission - you can still use your car-hierarchy: every Car has its
own engine, fully defined in derived classes.
Waiting for comments from other members :)

hbrt
 
T

Tim

Hi, Tim!
I would rather do this in following way:
1. class Car should have two virtual public (as in your 2. solution)
2. class Car should have two handlers for Engine and Transmission -
but in PROTECTED section
3. class FordCar, derived from Car, should have overloaded functions
from its ancestor
Pros of this solution:
- you cannot create just a 'car' - it has to be FordCar, OpelCar,
FiatCar etc.
- protected section allows you to use both handlers in derived classes
- if you ever try to create a class hierarchy for Engine or/and
Transmission - you can still use your car-hierarchy: every Car has its
own engine, fully defined in derived classes.
Waiting for comments from other members :)

hbrt

I have some questions on your implementation:
1. FordCar has to implement the virtual set.. functioins? Is it
repeating code?
2. In set engine to Ford, you need to check the engine type?
3. I am very interested you talking about the engine/transmission
hierarchy, considering these, it there any better design for the whole
system?
Thanks.
 
H

hbrt

I have some questions on your implementation:
1. FordCar has to implement the virtual set.. functioins? Is it
repeating code?
2. In set engine to Ford, you need to check the engine type?
3. I am very interested you talking about the engine/transmission
hierarchy, considering these, it there any better design for the whole
system?
Thanks.

ad 1:
FordCar will reimplement set of virtual functions. As well as other
types (subclasses) of Car. Repeating code? It is not so obviously: if
you have ONLY class Car and class CarFord and you don't intend in the
near future to add other cars - then it is repeating code. But
consider this: you have multiple car-derived classes, all having the
same public API: setEngine() and setTransmission(). Using polimorphism
- it makes your code easier to maintanance. But - if all cars have the
same way to setEngine() - then don't make this function virtual, just
define its body in class Car - no code repetition :)

ad 2:
It is hard question. It depends on the way you prepare the engine. If
you try make hierarchy for engines - and you use:
Car* carPointer = new FordCar();
carPointer->setEngine( new Engine(maybe_some_arguments) );
then you have to check wheter this particular Engine is for Ford only
(I assume this is your concern - never use engine for inpropriate car
producent) or not.
You can also move handlers for engine and transmission lower in car
hierarchy and define, that all FordCars should have FordEngine*
pointers. But then your virtual functions are not useful... I think,
that if problem is with vendor name, then maybe each car/engine/
transmission should have their own string with vendor name? Then
simply check these, while using polimorfic mechanism:
class Car
{
public:
virtual void setEngine( Engine* ) = 0;
string vendor;
};

class FordCar : public Car
{
public:
void setEngine( Engine* e) { if (e->vendor==this->vendor) continue;
else return; }
};

class Engine
{
string vendor;
};
class FordEngine : public Engine
{
};

It's up to you what you need and how you do it :) These are only some
proposals.

ad 3:
I know that using three (or more) pararell hierarchies is bad. It is
hard to handle everything so closly connected. Here you would have
Cars, Engines, Trasmissions, possibly more&more&more... If you add new
class, eg. NewGreatPolishCar, you also has to add its Engine class,
Transmission class etc. It's bad. Try to find other solution, maybe
Engine class (for example) doesn't use great advantages from
inheritance? Or maybe it is connected only to Car by itself, and the
only difference is in vendor name?

Still waiting for members discussion. Especially about this last
paragraph. How can one destroy so closely connected hierarchies?
Best regards,

hbrt
 
R

Ron Natalie

Tim said:
Dear All,

For the car case I posted before (car has some parts, and parts must
have the same maker, such as Ford), what I really concerned is that:
Second poster with the same question. School must be back in
session. Kiddies do your own homework.
 
T

Tim

ad 1:
FordCar will reimplement set of virtual functions. As well as other
types (subclasses) of Car. Repeating code? It is not so obviously: if
you have ONLY class Car and class CarFord and you don't intend in the
near future to add other cars - then it is repeating code. But
consider this: you have multiple car-derived classes, all having the
same public API: setEngine() and setTransmission(). Using polimorphism
- it makes your code easier to maintanance. But - if all cars have the
same way to setEngine() - then don't make this function virtual, just
define its body in class Car - no code repetition :)

ad 2:
It is hard question. It depends on the way you prepare the engine. If
you try make hierarchy for engines - and you use:
Car* carPointer = new FordCar();
carPointer->setEngine( new Engine(maybe_some_arguments) );
then you have to check wheter this particular Engine is for Ford only
(I assume this is your concern - never use engine for inpropriate car
producent) or not.
You can also move handlers for engine and transmission lower in car
hierarchy and define, that all FordCars should have FordEngine*
pointers. But then your virtual functions are not useful... I think,
that if problem is with vendor name, then maybe each car/engine/
transmission should have their own string with vendor name? Then
simply check these, while using polimorfic mechanism:
class Car
{
public:
virtual void setEngine( Engine* ) = 0;
string vendor;

};

class FordCar : public Car
{
public:
void setEngine( Engine* e) { if (e->vendor==this->vendor) continue;
else return; }

};

class Engine
{
string vendor;};

class FordEngine : public Engine
{

};

It's up to you what you need and how you do it :) These are only some
proposals.

ad 3:
I know that using three (or more) pararell hierarchies is bad. It is
hard to handle everything so closly connected. Here you would have
Cars, Engines, Trasmissions, possibly more&more&more... If you add new
class, eg. NewGreatPolishCar, you also has to add its Engine class,
Transmission class etc. It's bad. Try to find other solution, maybe
Engine class (for example) doesn't use great advantages from
inheritance? Or maybe it is connected only to Car by itself, and the
only difference is in vendor name?

Still waiting for members discussion. Especially about this last
paragraph. How can one destroy so closely connected hierarchies?
Best regards,

hbrt

For the third concern, how about this:

A car hierarychy, A engine hierarchy, other parts hierarchy, and a
factory hierarchy

For the car hierarchy:

class Car is abstract and contains all the parts
class FordCar has a private constructor but frindly to FordFactory,
FordCar inherits parts and other method from class Car, thus it is
kind of blank.

class FordCar : public Car
{
friend class FordFactory;
private:
FordCar();
};

For the factory hierarchy:

class Factory
{
public:
virtual Car* BuildCar();
virutal Engine* BuildEngine();
... //other parts
};

class FordFactory
{
public:
virutal FordCar* BuildCar();
virtual FordEngine* BuildEngine();
... //other parts
};
 
J

Jerry Coffin

[ ... ]
The difference is that I put the private part members is the derived
classes. I want to know which design is better and why?

There could only be a "better" design if one of the designs was "good".
IMO, that's not the case, so the question has no real answer.

You're mistaking values for behaviors. Different types have different
beaviors. In this case, the objects are all really of the same type,
with the same behaviors, but different values for one or two fields.

You can argue that there's a minor difference in behavior -- attempting
to build a Ford car with a Chrysler engine would fail to compile with
your code, but would typically do something like throwing an exception
when the two cars are the same type, with different values for
manufacturer.

IMO, however, your design multiplies the classes by a huge number for
this (mostly theoretical) improvement in type-safety. It also makes it
impossible to deal with exceptions, such as Ford cars with Cosworth
engines. In theory, you could derive CosworthEngine from FordEngine, but
this wouldn't be correct either, since you can't arbitrarily substitute
a Cosworth engine for a Ford engine.

If you insist on making these separate types anyway, the least you can
do is use templates so you don't have a zillion duplicates of
essentially identical code, one for each car manufacturer on earth.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top