The output of a program is a2a3. I understand, that class E has two "base instances", because inheritance from B is not virtual. Can anybody explain why set_c is called from one "base instance" of class B in class E and get_c - from another?
The code is from here: http://www.interqiew.com/ask?ta=tqcpp04&qn=2
#include <iostream>
class A
{
public:
A(int n = 2) : m_n(n) {}
public:
int get_n() const { return m_n; }
void set_n(int n) { m_n = n; }
private:
int m_n;
};
class B
{
public:
B(char c = 'a') : m_c(c) {}
public:
char get_c() const { return m_c; }
void set_c(char c) { m_c = c; }
private:
char m_c;
};
class C
: virtual public A
, public B
{ };
class D
: virtual public A
, public B
{ };
class E
: public C
, public D
{ };
int main()
{
E e;
C &c = e;
D &d = e;
std::cout << c.get_c() << d.get_n();
c.set_n(3);
d.set_c('b');
std::cout << c.get_c() << d.get_n() << std::endl;
return 0;
}
C++ name lookup takes into consideration the sub-object of a class that is being looked in, and associates the sub-object to the name it finds. This association is to know what object the member function should operate on. Once the name is found and is associated with one object (the lookup is unambiguous), lookup stops. The rules are rather more complex than the summary I presented, but we can already reason about your code. Your difference in result stems from using d.set_c('b')
and c.get_c()
.
d
and c
are bound to the D
and C
sub-objects of e
, respectively.
You start the lookup for the setter set_c
in the D
sub-object of e
. This means that the instance of B
it will find and associate the setter with is that one that resides in the D
object. The lookup stops there.
For the getter get_c
, you start the lookup in the C
sub-object, so the B
that is associated with the getter is the one that resides in the C
sub-object. Now the lookup stops here.
As you noted already, those are different sub-objects, so the getter and setter don't operate on the same data.