12117

Is a pure virtual function actually selected in overload resolution?

From a comment of mine in a previous question :

Since there can't be instances of abstract classes a pure virtual function can never be selected after overload resolution

The obvious response was :

abstract_class* a = new derived_class; a->pure_virtual_function();

and the best proof of correctness saying :

Dynamic dispatch occurs at runtime, based on whichever object is actually being used at that time. Overload resolution occurs at compile time.

<hr>

Yet what bothers me is that when <strong>resolving explicitly the scope of a class member in our case compilation fails</strong>, so it looks like a pure virtual function is never actually selected through overload resolution :

struct B { virtual void copy(B const& rhs) = 0; }; struct D : B { void copy(B const& rhs) { D const *pd = dynamic_cast<D const*>(&rhs); if (pd) { y = pd->y; } } int y; }; int main() { D d1, d2; d1.y = 2; d2.y = 5; B *p1(&d1), *p2(&d2); //////////////////////////////////////////// (*p1).B::copy(*p2); //////////////////////////////////////////// return 0; }

Error message

undefined reference to `B::copy(B const&)'

<strong>Demo</strong>

<strong>What's the case here and if the pure virtual function is actually chosen in overload resolution why can't I "force" the compiler to do the same thing (as the resolution does).</strong>

Answer1:

A pure virtual function can be selected by overload resolution. In most cases it will not be called though. Its final overrider will be called instead, just like with any other virtual function.

struct A { virtual void foo() = 0; void foo(int); }; A* getA(); int main () { A* a = getA(); a->foo(); } struct B : A { void foo() {} }; A* getA() { return new B; }

Overload resolution selects A::a() (<strong>not</strong> B::a()) at compile time, then B::a() is found and called at run-time by the virtual dispatch mechanism. Purity is irrelevant here.

Answer2:

If I understand, you really have two questions. Both are addressed here:

Why does compilation fail?

It fails because you have explicitly attempted to invoke a pure virtual function with no implementation. However, pure virtual functions may be implemented. Here is a single line implementation that will cause your code to successfully compile and run:

void B::copy(B const& rhs) { std::cout << "I am pure and virtuous\n"; }

Is a pure virtual function actually selected in overload resolution?

In a word, no, not in this case. But there is a case in which a pure virtual function must be implemented and will be called (but strictly speaking, not due to overload resolution). That case is when there is a pure virtual destructor of a base class. See this SO question for more detail on why and how.

However, a pure virtual function may be selected in overload resolution. Add this to B

void B::copy(B const& rhs) const { std::cout << "I am pure and virtuous and constant\n"; }

And a corresponding function in D:

void copy(B const& rhs) const { /* do nothing */ }

You will find that overload resolution causes only "I am pure and virtuous" to be printed.

Recommend

  • How to have an email link inside a text in Xaml?
  • F# slicing array by indices array
  • How do I install these PHP extensions on Ubuntu?
  • How to compile unsafe code in MonoDevelop 2.4
  • “Yesod devel” fails with fromJust in devel.hs
  • Display Current Video in Windows Phone 8 using AudioVideoCaptureDevice?
  • Can't use openlayers-3 with webpack
  • Hatch area using pcolormesh in Basemap
  • Rx produce and consume on different threads
  • XNU incudes in Kext
  • In C what exactly happens if i use () to initialize a double dimension array instead of the {}?
  • Symfony 2 error page response
  • I am receiving HibernateException “No Hibernate Session bound to thread, and configuration does not
  • Using $compile in a directive triggers AngularJS infinite digest error
  • Updating Dojo provide
  • Which open source license has no forking [closed]
  • How to explicitly/implicitly implemented interface members in C++/CLI?
  • SetWindowsHookEx does not react on media keys
  • Is it possible to access block's scope in method?
  • Alert pop up with LWUIT
  • Get one-time binding to work for ng-if
  • Fetching methods from BroadcastReceiver to update UI
  • How to recover from a Spring Social ExpiredAuthorizationException
  • output of program is not same as passed argument
  • Does CUDA 5 support STL or THRUST inside the device code?
  • How to make Safari send if-modified-since header?
  • How to pass list parameters for each object using Spring MVC?
  • bootstrap to use multiple ng-app
  • Unit Testing MVC Web Application in Visual Studio and Problem with QTAgent
  • CSS Applying specific rule for a specific monitor resolution with only CSS is posible?
  • Trying to get generic when generic is not available
  • Java static initializers and reflection
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • How can I remove ASP.NET Designer.cs files?
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • unknown Exception android
  • JaxB to read class hierarchy
  • Observable and ngFor in Angular 2
  • Unable to use reactive element in my shiny app