Inheritance issue

I have the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

class A
{
public:
    virtual void f(int n) { std::cout << n << 1; }
    virtual ~A() { }

    void f(int n) const { std::cout << n; }
};

class B
    : public A
{
public:
    void f(int n) { std::cout << (n << 1); }

    void f(int n) const { std::cout << n + 1; }
};

int main()
{
    const A a;
    B b;
    A &c = b;
    const A *d = &b;

    a.f(2);
    b.f(2);
    c.f(1);
    d->f(1);

    std::cout << std::endl;

    return 0;
}


Answer is 2421

I have guessed all the above correctly except for the last call d->f(1);.

My question is:
why is the d->f(1) calls the non-virtual function f in class A despited the fact that base class pointer "d" is initialised to the address of the derived class B.

Please explain why this is happening?

Many thanks in advance.

because the function is non-virtual
why is the d->f(1) calls the non-virtual function f in class A despited the fact that base class pointer "d" is initialised to the address of the derived class B.
Exactly because it is non-virtual.
the fact that base class pointer "d" is initialised to the address of the derived class B
...do not matter at all, because it is the pointer to A and threated as such.
When you declare function virtual it tells compilet that it should save information on which function it should actually call in the object itself. It does not do that for non-virtual functions so function called will be chosen depending on pointer type and not on actual type of the object.
...do not matter at all, because it is the pointer to A and threated as such.
When you declare function virtual it tells compilet that it should save information on which function it should actually call in the object itself. It does not do that for non-virtual functions so function called will be chosen depending on pointer type and not on actual type of the object.


Ok sure, but in class A we have a vitual version of function f , why doesn't the compiler use the virtual version to call the overriden function f in object b?

I do not understand that fully.

The next question is:
When class A has two functions f (virtual and non-virtual) how does the compiler know which one to call, surely we cannot override function f inside the same class (i.e. A)?
Ok sure, but in class A we have a vitual version of function f , why doesn't the compiler use the virtual version to call the overriden function f in object b?

The non-virtual version is an overload for const objects. Because d is a pointer to const A, the compiler is required to call the appropriate overload which happens to be nonvirtual.

In other words, the nonvirtual function is the only one which fits the cv-qualified arguments.


When class A has two functions f (virtual and non-virtual) how does the compiler know which one to call, surely we cannot override function f inside the same class (i.e. A)?


I believe you mean overload rather than override, and yes, we can.

http://en.cppreference.com/w/cpp/language/overload_resolution
I believe you mean overload rather than override, and yes, we can.


Well overloading would happen within a class, that's true. But overloaded function f must have different function signature by having different type or number of into parameters. In this case in class A both functions f have the same type and number of input parameters.
This is not overloading, is it?
closed account (10X9216C)
const is the reason why, what you want to look at is the way functions are actually interpreted. A method passes a pointer to the object, it just hides the details from the user.

1
2
3
void A::f(int n) const { std::cout << n; } // is actually just:
void A::f(const A* this, int n) { std::cout << n; }
void A::f(      A* this, int n) { std::cout << n << 1; } // without const 
But overloaded function f must have different function signature by having different type or number of into parameters
cv-qualifiers are part of function signature.

std::vector has operator[](size_type) and operator[](size_type) const overloads for example
The last two comments are exactly what I wanted to know and wasn't 100% sure on.

Many thanks for your informative comments.
Topic archived. No new replies allowed.