Sign in to follow this  
Vish

Quick C++ question.

Recommended Posts

Hi. I was wondering if there is any possible way to do what I am about to describe in C++. And if there is - How? I have a class lets call it A.
class A {
public :
virtual void mem1() =0;
virtual void mem2() =0;
};
I want to create another class B, which is derived from A(public), but I want to redefine a members function, so that it becomes something like this.
class B : public A {
public :
virtual void mem1() 
{
   //Add certain checks
   //Then call mem1 (of it's derived class).
   //Add some more checks
}
};
And now If I create a class C, which is derived from B and I alter the member function "mem1" (Since it's virtual). I still wants those checks to occur. I know one way is the create a new pure virtual member function, and place it inside B's mem1 function, but is there any way I can do this without creating a new function (I basically want the new function to have the same name.) I doubt, this is possible. But I just thought I should ask. Any suggestions ?

Share this post


Link to post
Share on other sites
No, I should have been clearer.

class A {
public :
virtual void mem1() =0;
};

class B : public A {
public :
virtual void mem1()
{
std::cout << "Preliminary Checks" << std::endl;
//Call function mem1(), but it should not be recursive,
std::cout << "Post-run checks" << std::endl;
}
};

class C : public B {
public :
virtual void mem1()
{
std::cout << "Hurray !! This is what I wanted" << std::endl;
}
};

C object;
object.mem1();


The output should be -

Preliminary Checks
Hurray !! This is what I wanted
Post-run checks


Do you think this is possible ?

EDIT :
@plastique : Yes, I can. And that is exactly what I'm doing right now. I was just wondering if there was some other way to emulate such behavior. I guess there isn't.
Thanks anyway.

Share this post


Link to post
Share on other sites
You don't have to call the same function but a different virtual function (and C doesn't override mem1 at all).

Otherwise it is not quite normal that base classes know about classes derived from them.

Share this post


Link to post
Share on other sites
This is one of the little annoyances of C++. Sometimes you want to ADD to a function's behaviour, not override the parent function entirely. In Java you can refer to "super" or some such thing, and call the parental version from the child, but in C++ you end up hardcoding the parent'sClassName:: to do that, which feels somehow dirty (and is easy to forget to do).

I can think of ways to help automate the process a bit, but they involve really ugly work with #define and wrapping the whole subclass definition in macros, and the more I think about it the less willing I would be to actually do that. Just erect a big, insulting comment explaining that in the case of function X(), the parental version must be called, and anyone that forgets is the benighted offspring of an especially foul, mutant earthworm. It may help people remember.

Share this post


Link to post
Share on other sites
Yeah, on the one hand that's like assuming the class knows about the derived class, on the other hand trying to have a nested call on an overridden function.

Maybe it would be better to completely rethink the whole task or for starters make those checks public (or protected) member functions which a derived class also is able to call.

Share this post


Link to post
Share on other sites
It could be done by calling B::mem1 twice from C::mem1 and keeping track of whether B::mem1 has been invoked before to switch between pre and post conditions:

#include <iostream>

class A
{
public:
virtual void mem1() = 0;
};

class B : public A
{
public:
B() : first_time(true) { }

void mem1()
{
if (first_time)
{
std::cout << "preconditions\n";
first_time = false; // do postconditions next time
}
else
{
std::cout << "postconditions" << std::endl;
}
}

private:
bool first_time;
};

class C : public B
{
public:
void mem1()
{
B::mem1(); // preconditions
std::cout << "C::mem1\n";
B::mem1(); // postconditions
}
};


int main()
{
C().mem1();
}

/*
output:

preconditions
C::mem1
postconditions
*/


You could take it a different way and have them recursively invoke each other (using CRTP to avoid B knowing about C expliticly) whilst making sure not to cause an infinite loop.

Neither of these are actually recommended in practice though, using another function is a vastly superior solution:

#include <iostream>

class A
{
public:
virtual void mem1() = 0;
};

class B : public A
{
public:
void mem1()
{
std::cout << "preconditions\n";
checked_mem1();
std::cout << "postconditions" << std::endl;
}

private:
virtual void checked_mem1() = 0;
};

class C : public B
{
private:
void checked_mem1()
{
std::cout << "C::checked_mem1\n";
}
};


int main()
{
C().mem1();
}

/*
output:

preconditions
C::checked_mem1
postconditions
*/

Share this post


Link to post
Share on other sites
@dmatter : Thanks for your response. The second method is the first thing that popped into my head, and I'm using it right now. I just thought I should research a little before jumping the gun.

@ScottMayo : - "the benighted offspring of an especially foul, mutant earthworm."- Hehe! Good one.

The main reason I wanted to do this was cause I already have class "C" implemented in a couple of places(various different versions), and now I would like to add certain checks and features without editing ever single class. So, I just though I would make a middle class with all those checks and features, and make the C class derive from it instead of from A.

Share this post


Link to post
Share on other sites
My I suggest the design pattern "template method"? Note that it has nothing to do with C++ templates.

#include <iostream>

class A
{
public:
virtual void mem1() = 0;

// do not forget virtual destructor!!!
virtual ~A() {};
};

class B : public A
{
public:
void mem1()
{
std::cout << "sanity check #1" << std::endl;
override_me();
std::cout << "sanity check #2" << std::endl;
}

protected:
virtual void override_me() = 0;
};

class C : public B
{
protected:
void override_me()
{
std::cout << "in C" << std::endl;
}
};

int main()
{
A* p = new C();
p->mem1();
delete p;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Vish
I just thought I should research a little before jumping the gun.
Always a good idea [smile]

Note a subtle difference between my implementation of the technique and DevFred's, namely that the abstract method (checked_mem1/overide_me) in my example is private but in DevFred's it's protected. The appropriate choice depends on whether classes deriving from C need to be able to call the abstract method directly without enforcing the pre/post conditions, or whether it should always be checked.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
the abstract method (checked_mem1/overide_me) in my example is private

Oh, you can override private member functions in C++? Cool. Java taught me that didn't make sense (there are no private virtual functions in Java, private functions are always statically bound).

Share this post


Link to post
Share on other sites
Quote:
Original post by DevFred
Oh, you can override private member functions in C++? Cool.
Absolutely! Obviously non-virtual functions could be overriden but when doing it with virtual functions you still get the dynamic resolution as usual.

In fact I recommend making almost all virtual function as private as possible. Public virtuals are useful for one-off classes and example code but for a stable interface public non-virtuals are the way to go. Public virtuals essentially require you to change to the public interface if you decide to apply the template method pattern at a later stage and it is too much of a useful refactoring to warrant giving it up.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this