0
votes

I understand the principle of why you can only call base class functions when assigning a derived class to a base class pointer. From my understanding of virtual tables the reason why is because only base class virtual function pointers are put into the virtual table so only they can be called but if the base class pointer points to a derived class, when the derived class constructor is called the base class virtual function is replaced with the override in the virtual table.

However my point is: are there going to be problems if you have a non virtual member function in the derived class that is used in a derived class override of a virtual base class member function.

My theory is there shouldn't because its a question of function access not jumps within the function, by assigning the pointer to new DerivedClass, you are assigning space for all the derived class, so access to the virtual overridden function is allowed using the pointer to the virtual function kept in the v-table. All actions from there onward are as if you were just in a derived class object so it can jump to whatever function it wants.

Is this correct? Or is there an issue with the jump in the function using the base class pointer as a jump reference (like an array: *pointer + 2 for function), is that how member functions are called?

If this is (not my intention but still) no issue, could it be theoretically possible to have a virtual function that takes, say an int argument. Then a switch statement inside the derived class override of the virtual function that, depending on int passed in, calls specific derived class functions thereby working around the 'only call base class defined virtual functions' problem?

eg. (skeleton with no constructors etc. and separation of declaration/definition)

class A
{
   protected:
          virtual void AFunc() ; 

} ;     

class B : public A
{
   public:
          virtual void AFunc() { BSpecificFunc() ;} // doable?
   /* if thats the case why not:
          virtual void Sfunv(int temp)
           {
              switch(temp)
                   {
                     case 1 : BSpecificFunca() ; break;
                     case 2:  BSpecificFuncb() ; break;
                     etc.  
                    }
            }
       */
   private:
          void BSpecificFunc() ; 
          void BSpecificFunca() ;
          void BSpecificFuncb() ;
          void BSpecificFuncc() ;

} ;  


int main()
{
   A *pBaseClass = new B;

   pBaseClass->AFunc(); //Will there be any issues doing this?

}

currently at design stage which is why I have kept this nice and theoretical.

2
It should be pretty simple to compile this little test program and see what happens! - krsteeve
You can't call the AFunc() like that, it is part of B and not a standalone function. - AndersK
edited for correction thanks 'claptrap' - user2248685

2 Answers

1
votes

If you call pBaseClass->AFunc() and pBaseClass is actually a B then B::AFunc() is what gets called. If pBaseClass is actually an A then A::AFunc() is what gets called. That's the whole point of polymorphism.

What B::AFunc() does is up to B, there's no reason it can't call other functions or use data within B that don't exist in A.

0
votes

There shouldn't be an issue - the call to the non-virtual function is already resolved. Think of it this way: B::AFunc() is compiled to something like call BSpecificFunc. That can be done at compile time.

The only challenge is to get to B::AFunc(), and for that we have the virtual table. But once we're there - there are no issues, the object pointer actually points to a B object (which is valid for BSpecificFunc, and the function call to BSpecificFunction is already resolved.