Link to home
Start Free TrialLog in
Avatar of Floater
Floater

asked on

Calling Base-Class functions

I'm working on an app that goes OO naturally, due to the hierarchical nature of the data.  What I'm having a problem with is where to stick some of the code.  I have an abstract base class (call it A) that B and C inherit from.  What I'd like to do is have code in A that is shared by both B and C.  I currently have a "display" function in B and C that share a pretty big chunk of initialization code.  What seems natural to me is to have a virtual "display" in A that does this setup, then call that from B and C before running their own code.  Is this possible?  Is there a better way?  Do I have to call the function something different in A?
ASKER CERTIFIED SOLUTION
Avatar of Shay050799
Shay050799

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Floater
Floater

ASKER

The initialization stuff isn't something that can go in the constructor... it's called at every "tick".  How does that change the answer?

Why can't A have pure virtuals if I don't want to instantiate it?

Why is the destructor virtual?
1 )what do u mean by "tick"  ?
2) u want to call some A function to do something right ? so u need to implement A in someway right, so A can't be Pure virtual, u can do it virtual not pure virtual.
pure virtual it mean that all its function declare like that:
virtual void Foo1()=0;
virtual int Foo2(int,char*)=0
etc...

it calls Interface.
3) when u declare you Base destructor as virtual it gurantee to be called after u destroy one of its derived class declare it the following way:

virtual ~A()

and u all set. now all the UnInitialize is in this destructor which will be called everytime one of the derived class destroy
Avatar of Floater

ASKER

I think I got it working...
"Tick" means the function is called about 100 times/sec, and the initialization stuff in A should happen each time.

What I'm doing is in A:
virtual output() {/* Init stuff */}

In B/C:
virtual output() {
    A::output()
    ...
}

Last question, unless theres a problem w/ the above:
If I do a virtual destructor, it automatically calls the base class's destructor for me?  This happens before the derived, correct?  And this doesn't happen for other, non-destructor functions?
u don't have to declare Output in B do this
class A
{
public:

      virtual void Init() {cout<<"A::Init";}
      virtual ~A() {cout<<"A::Detructor";}
};
class B:public A
{
};

void main(void)
{
      A* a;
      a=new B;
      a->Init();
}

no the B destructor called first but than it calles the base class destructor
it depends on the way u declare it.
if u declare it like that:
A* a=new B
it never calles B destructor


Avatar of Floater

ASKER

I know I don't have to, but the point was to share the output() code from A in both B and C's output() function as the beginning segment.  Thanks for the help.

it does share, call Output from B or C it automatically called the A function thats the idea of OO
>> Why can't A have pure virtuals if I don't want to instantiate it?

>>u want to call some A function to do something right ?
>> so u need to implement A in someway right, so A can't be
>> Pure virtual, u can do it virtual not pure virtual.
>> pure virtual it mean that all its function declare like that:
>> virtual void Foo1()=0;
No.  First of all A can be a pure abstract class in this case, and probably should be.  Secondly a pure virtual function may have an implimentation, so the output function is a good candidate for being pure-virtual.

>> when u declare you Base destructor as
>> virtual it gurantee to be called after u destroy
>> one of its derived class
It is guaranteed to be called anyways.  That is, it will be called if it is virtual or not.  Making a destructor guarantees that the DERIVED class destructors, not the BASE class destructors will be called.

>> it does share, call Output from B or C it automatically
>> called the A function thats the idea of OO
Not automatically.  You must make it do so.  floater's code does so.  
>> I know I don't have to, but the point was to share
>> the output() code from A in both B and C's output()
>> function as the beginning segment
Shay, you want to say something on that point?  that was the question, right?

floater there are two approaches to this sort of problem.  

One is the approach you took where the derived class has a function that calls on the base class version of the function to perform part of the processing.  In your case the B and C classes override the output() function and within these overrides they call on the A class's version of the function.  In this case the function does not have to be virtual, although it may be a good idea for it to be so, it just depends on how this will be used.

The other approach is to define the function in the base class only and to have this function perform the "shared" processing.  Then have this function call on one or more virtual "notification" functions.  These notification functions would be overidden in the derived class and would allow those classes to perform their class-specific processing.

Which approach to take will depend on the circumstances in which the code is being used.  However I find that the 2nd approach tends to be better in a majority of the cases.
Avatar of Floater

ASKER

The situation is for an OpenGL rendering interface;  Object A is a root "3D object" class, and B and C are specific object types w/different behaviors.  I want to put stuff generic to 3D object display into A's display code, so it does the startup stuff like turning on or off lighting based on the flags in A.  The reason I'm leaning toward the first way you describe instead of notification functions is that later, I want to call display() on a list of type A*, where the objects are B's and C's.  This will call the B and C display(), and they'll call the parent's display() for the shared code.

Is there some advantage to notification functions over this method?  They seem functionally equivalent initially.

(BTW, I already gave out points for this one, after I figured out the parent calling.  Is there some way I can send you points for the helpful comments?)
>> Is there some advantage to notification
>> functions over this method?
either will work--they are interchangable.  But one may be better than the other in terms of how easy they are to maintain over time (as the program's needs change.)  For example, in your case you always want the base clase (A) version fo the procedure to be called to perform some "set-up" steps before the derived class begins its work.  Now what if you later add a class D, but in D's version of output, you forget to call the base class version of output.? opps!  If you used a design like

class A
{
   virtual void OutputNotification() {} =0;
public:
   void output()
   {
       // Do setup stuff.
      OutputNotification();
   }
};

Then when you add new classes, they only need to redefine OutputNotification (which they must do) and the setup steps will automatically be performed by the Output procedure.  

Now this addvantage is also its dissadvantage, what if you add class E and in this class you don't want the setup steps performed?  There are two ways around that, 1) use the design you suggested and make sure to call the base class version when needed, or 2) use the design I suggested above AND make the output function virtual as well.  Then the B, C, and D classes only need to redefine the notification function and are assured that they get the propper setup performed automatically, and the E class can redefine the output function so that no setup (or different setup) is done.  This second option is very powerful, but may add a lot of virtual functions to the class that aren't completely necessary.

>> I already gave out points for this one, after
>> I figured out the parent calling
In the future make sure not to grade answers that are incorrect or unhelpful (if you can tell they are incorrect...)  If an expert is not being helpful--don't reward him/her.

>> Is there some way I can send you
>> points for the helpful comments
That's alright.  I just didn't want to see you left with a lot of wrong information.