سؤال

I have a virtual function that is implemented in a base class A. This function has a loop in it. A derived class B is available but does not override the virtual function as the code is the same for any derived class.

Well, however, I need an additional condition check inside that virtual function (local_policy) that should be called depending on class type (base or derived). Now, I could implement another virtual member function and override it in the derived class however as the call happens inside of a loop the virtual overhead should be minimized, so I thought I rather use a function template and specialize it for any derived classes.

Now the problem is that I am passing *this pointer to the function template from within foo() and the specialization is never called. Is the this pointer in this certain case of type A instead of B? I would have guessed it is not and that my specialised function template would be called.

I appreciate any help!

template < typename T >
bool local_policy(const T* mtype) { return true; }

class A
{
   public: 
   virtual void foo()
   {
      for(..) { 
         if(local_policy(this)) //This will call the non-specialised template! Why?
         { /* do something */ }
      }
   }
   /* [...] */
}

class B : public A
{         
   /* [...] */
   //foo() is not overridden here
}

//Specialize the function template for class B
template <>
bool local_policy(const B* mtype) { return false; }

main()
{
   B* test = new B; if(!B) return;
   test->foo(); 
}

Thanks in advance! Best

P.S.: I also tried some C++11 using a normal function and a global template with std::enable_if to only enable if it is a derived class. Doesn't matter, also that one is not called as I expected. :-/

هل كانت مفيدة؟

المحلول

C++ does not allow dynamic dispatch based on argument types -- function overload resolution is always based on the static type of the expression. In your example, the static type of this with always be A *, even when it points at a B, so your specialized function will never be called.

If you want dynamic dispatch, you must use a virtual function, and you can only dynamically dispatch based on the this argument, never any other arguments. If you're worried about the overhead, you can hoist the dynamic call out of the loop and only call it once:

virtual bool local_policy() { return true; }
virtual void foo() {
    bool policy = local_policy();
    for (..) {
        if (policy) {
            /* do something */
        }
    }
}

The compiler can't ever do this optimization on its own, since it doesn't know that you'll never define a derived class that overrides the local_policy function with something that has side effects...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top