0

In the following code

#include <iostream>
using namespace std;

class A {
  public:
    A() {}
    virtual ~A() {};
};

class B : public A {
  public:
    B() {}
    virtual ~B() {};
};

void process(const A&) {
    cout << "processing A" << endl;
}

void process(const B&) {
    cout << "processing B" << endl;
}

int main(void) {
    A* a = new B;
    process(*a);
    return 0;
}

the output of running it becomes

processing A

but I would have assumed that it should have been

processing B

since a points to the derived class B and not A. So why does it call the first implementation of process function and not the second?

3 Answers 3

2

The static type of expression *a is A because a was declared as

A* a = new B;

The compiler resolves the selection of overloaded functions using the static type of the argument.

Even when virtual functions are called the compiler uses the static type of the object to call appropriate function. The difference is only that the compiler uses the table of pointers to virtual functions to indirectly call the required function.

Sign up to request clarification or add additional context in comments.

7 Comments

The type of *a is actually A&.
@iavr From the C++ Standard: "If the type of the expression is “pointer to T,” the type of the result is “T.”
Instantiating decltype(*a)::dummy() results in 'decltype(*a)' (aka 'A &') is not a class, namespace, or scoped enumeration. Same for decltype((*a)). Maybe I'm missing something?
@iavr You missed the quote of the Standard I cited.
@iavr The compiler returns lvalue that is the same object as the original that is refered to. This reference has type T.
|
2

You need to make process() a virtual member function of A, B:

class A {
  public:
    A() {}
    virtual ~A() {};
    virtual void process() const { cout << "processing A" << endl; }
};

class B : public A {
  public:
    B() {}
    virtual ~B() {};
    virtual void process() const override { cout << "processing B" << endl; }
};

int main(void) {
    A* a = new B;
    a->process();
    return 0;
}

In your current code, *a is of type A&, so the closest match to process(*a); is the first overload (for const A&).

Comments

1

void process(const A&); is a better (exact) match, since dereferencing A* gives you A&.

Short answer, but there isn't much more to say unless you want a reference from the standard.

You could dynamic_cast the result of *a and that would give you a B&, but that's smelly desing. What you probably want is a virtual function in A that's overriden in B (assume it's called foo). Then, calling a->foo() would dispatch to B::foo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.