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

Comment

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:Is a pure virtual function actually selected in overload resolution?