I came across the following c++ code in an online test.
#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;
}
The code outputs a2a3 but I don't get it. Why does this run at the first place isn't the class B methods ambiguous? Also class E is not virtually inherited.
Since c
has type C&
and d
has type D&
, there's no ambiguity - both C
and D
have exactly one B
subobject.
(c
and d
literally refer to the respective subobjects of e
- they don't refer to "e
, but under a different type".)
The reason that the output is "a2a3" and not "a2b3" or "a2a2" is that A
is inherited virtually, so there is only one A
subobject in E
and thus only one n
member.
The C
and D
subobjects have one B
subobject each, and d.set_c('b');
modifies the one in d
but not the one in c
.