Reputation: 928
I have written a program according to a specification.
The Specification has about 3 types and each type gets handled differently on every single point.
That means more or less for code readability, I have written it like shown below, now my question is, if you have 200 such statements, wouldn't it be worth to merge them all into one "if enum-type x"
I would believe there is a program out there which already does it but google didn't help me much for this specific problem. Thanks for help in advance.
/* Point 1.15 Filling Customers bdate */
if(current.identifier == APPLE){ output.setValue(1.15, additionalObj.some.color)}
if(current.identifier == PLUM){ output.setValue(1.15, otherObj.another.color) }
if(current.identifier == GRAPE){ output.setValue(1.15, default::color) }
/* Point 1.16 Filling Customers cash*/
if(current.identifier == APPLE){ do whatever}
if(current.identifier == PLUM){ do whatever}
if(current.identifier == GRAPE){ do whatever}
Result to be achieved:
if(current.identifier == APPLE){ output.setValue(1.15, additionalObj.some.color)
do whatever
}
And so on so i can merge them into 1 statement automatically while i still have the readable code
Edit: I might have misinformed you, its actually not a type its just an Object with a String identifier and SubObjects so i can't use polymorphism. I have adjusted the above so you can see what i would like to achieve.
Upvotes: 1
Views: 461
Reputation: 1462
Read about C++ class inheritance and polymorphism if you have not understood them already. These two features of C++ will provide a more elegant way to solve your problem.
Upvotes: 5
Reputation: 19349
There's two ways I would to do this: the first is by polymorphic behaviour (either via virtual functions, or type parameterization); the second would be to switch
on the type.
For the first one, each of the type can inherit from a common (possibly abstract) base class:
class Base
{
public:
virtual void DoSomething( ) =0;
};
class A : public Base
{
public:
void DoSomething( )
{
cout << "I'm doing something from A!" << endl;
}
};
class B : public Base
{
public:
void DoSomething( )
{
cout << "I'm doing something from B!" << endl;
}
};
This way, you can simply use a variable of type Base &
, Base *
, or any smart pointer of Base
(e.g. shared_ptr<Base
), and call the DoSomething
method on that variable. The correct implementation of DoSomething
would be called based on the run-time type of the variable (since DoSomething
is a virtual method).
Another way to acheive similar behaviour is via templates. It's used in a similar way as the first suggestion, but you don't need a base class, and the methods need not be virtual:
class A
{
public:
void DoSomething( )
{
cout << "I'm doing something from A!" << endl;
}
};
class B
{
public:
void DoSomething( )
{
cout << "I'm doing something from B!" << endl;
}
};
Then the function which handles the operations can be defined something like this:
template<typename T>
void PolymorphicDoSomething( T variable )
{
T.DoSomething( );
}
and used like this:
A a;
PolymorphicDoSomething( a );
Of course, this example is a little contrived, but that's the fundamental idea, and can be very useful depending on the situation.
The other possibility would be to essentially do what you're doing now, but with a single switch
statement, rather than several if
statements. If the type of the variable is stored as an enum
or an int
, you can use a switch to efficiently determine which operations to perform:
enum VariableType
{
TypeA,
TypeB,
TypeC,
// etc.
};
//...
switch(variable_type)
{
case TypeA:
DoSomethingForA( );
break;
case TypeB:
DoSomethingForB( );
break;
case TypeC:
DoSomethingForC( );
break;
// etc.
}
But I doubt that this would really be any more effective than using virtual methods. Also, virtual methods are more managable - in order to extend the functionality, you must simply declare another class, and all the code you already have will be able to cope with it. In the case of a switch, you would have to add a case statement everywhere you check the variable's type. So I would really stick with virtual methods in this case.
Upvotes: 1
Reputation: 6834
Basic polymorphic approach:
enum Type { tX, tY, tZ};
struct Data
{
Type type;
int data_;
};
class Processor
{
public:
virtual void fillCustomersBDate(const Data& data) = 0;
virtual void fillCustomersCash(const Data& data) = 0;
};
class XProcessor : public Processor
{
virtual void fillCustomersBDate(const Data& data) { /* X stuff */}
virtual void fillCustomersCash(const Data& data) {/* X stuff */}
};
class YProcessor : public Processor
{
virtual void fillCustomersBDate(const Data& data) {/* Y stuff */}
virtual void fillCustomersCash(const Data& data) {/* Y stuff */}
};
void process(const Data& data)
{
Processor* processor = processorForType(data.type);
// Do general stuff
processor->fillCustomersBDate(data);
// Do general stuff
processor->fillCustomersCash(data);
// Do general stuff
delete processor;
}
More likely, you'd move most of the main flow into the base class.
Upvotes: 3
Reputation: 881783
If they're all distinct, you can separate them into individual sections like:
if (type x)
processX1v1_thru_1v15(); // will do all steps 1.1 thru 1.16 for type x
else if (type y)
processY1v1_thru_1v15(); // will do all steps 1.1 thru 1.16 for type y
: : :
and so on.
But you may want to look into polymorphism which will allow you to specify a different "whatever" for each class/type. The you can just do domething like:
obj.doWhatever1_01(); // calls obj-specific method depending on type.
obj.doWhatever1_02();
: : :
obj.doWhatever1_16();
Upvotes: 0