Reputation: 11
class X {
X(int, int); //constructor
void func();
}
class Y {
public int func() {
X x(5,7);
// some other random operations.
x.func();
}
}
Now, if I have to just initialize x based on some conditional, how do I do it?
class Z {
// only refer to x when mycond is true.
public int func(boolean mycond) {
if(mycond)
X x(5,7);
//same random operations;
if(mycond)
x.func();
}
}
One way to do the above in an unaesthetic manner is:
class Z {
// only refer to x when mycond is true.
public int func(boolean mycond) {
if(mycond) {
X x(5,7);
//same random operations;
x.func();
}
else {
//same random operations
}
}
}
I am looking for something more simpler where I don't have to repeat the code.
Upvotes: 1
Views: 1343
Reputation: 21
your requirement is just not to repeat somethings, you could use the null object pattern.
class Base
{
};
class X : public Base
{
};
class NullX : public Base
{
};
then
int funX(boolean mycond) {
Base* p = NULL;
if (mycond)
p = new x(5,7);
else
p = new NullX;
//... some other
//if (mycond)
p->func();
}
then we could remove the second if statement.
and further more, if your my condition is only for controlling the X, then the funX will be:
int funX (Base& x)
{
//some other
x.func();
}
and the mycondtion will be another function,
Base* getBase(int mycond)
{
if (mycond)
return new X(5, 7);
return new NullX;
}
then the function will be completely refactored.
Upvotes: 0
Reputation: 67479
The obvious solution is to use a pointer, or an auto pointer:
class Z {
public:
// only refer to x when mycond is true.
int func(boolean mycond) {
std::auto_ptr<X> px;
if(mycond)
px = new X(5,7);
//same random operations;
if (px.get() != 0)
px->func();
}
}
Upvotes: 1
Reputation: 40613
In the example that you gave, it is not clear why you cannot just write it as:
class Z {
// only refer to x when mycond is true.
public:
int func(bool mycond) {
//same random operations;
if(mycond) {
X x(5,7);
x.func();
}
}
};
However, if for some reason this is not desirable (for example, if the constructor for X
has some side effect which must happen before "some random operations"), then you should look at boost::optional
:
class Z {
// only refer to x when mycond is true.
public:
int func(bool mycond) {
boost::optional<X> x;
if (mycond) x = X(5,7);
//some random operations;
if (mycond) x->func();
}
};
If you don't want to use boost::optional
for some reason, then a similar effect can be obtained with a union
:
class Z {
// only refer to x when mycond is true.
public:
int func(bool mycond) {
union OptionalX {
OptionalX() {}
X value;
} x;
if (mycond) new (&x.value) X(5,7);
try {
//some random operations;
if (mycond) {
x.value.func();
x.value.~X();
}
}
catch (...) { if (mycond) x.value.~X(); }
}
};
That said, this will cause the introduction of a name into a scope where that name only sometimes has meaning. This is highly questionable, and you should probably consider using a different design.
Upvotes: 4
Reputation: 153909
The obvious answer is to put the other random operations in a separate function, so your code becomes:
int
func()
{
if ( myCondition ) {
X x( 5, 7 );
otherOperations();
x.func();
} else {
otherOperations();
}
}
You should probably do this anyway, if only to make the function readable and maintainable.
Upvotes: 2
Reputation: 13872
How about using new
and pointer (*)
X *xPtr = 0;
class Z
{
// only refer to xPtr when mycond is true.
public int func(boolean mycond)
{
if(mycond)
{
xPtr = new X(5,7);
}
//same random operations;
if(xPtr)
{
xPtr.func();
}
}
// and don't forget delete xPtr;
}
and see if above code can be refactored as following:
X *xPtr = 0;
class Z
{
// only refer to xPtr when mycond is true.
public int func(boolean mycond)
{
//same random operations;
if(mycond)
{
xPtr = new X(5,7);
xPtr.func();
}
}
// and don't forget delete xPtr;
}
Upvotes: 0
Reputation: 3250
You could factor out the "random operations", like this
if (my_cond) X x(5, 7);
random_operations_factored_out(T& a, U& b, const W& c, ..); // all the references that you need
if (my_cond) X.func();
Obviously you can (should?) encapsulate the context better, I used pass-by-reference for the sake of an example.
Another possibility is to encapsulate the logic in a pair of constructor and destructor, like
class X_caller{
private:
bool cond;
X x;
public:
X_caller(bool cond, int param1, int param2):cond(cond){
if (cond) {x = X(param1, param2);}
}
~X_caller(){
if (cond) x.func();
}
}
Now you will use this like this
{
X_caller(my_cond, 5, 7);
// all your operations
} // at the end of the scope the destructor of X_caller calls x.func() only if my_cond was true
// but you "can't see" this function call if you don't know the body of X_caller, so be careful!
// You have to document this kind of behaviour otherwise it's too obscure for future maintenance.
In all cases you have to make sure that all the resources (variables etc) which must be accessed are available to the factored out code.
The balance between the various choices depends on the complexity of the code: always try to reduce potential confusion in the reader of the code. This could come from long repeated piece of codes, or from "hidden" calls or from many other source, and you should try to reduce it if possible.
Upvotes: 0