Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ virtual classes: interesting point

Please tell me why the output is as below for the following program. I am not getting the virtual classes in c++. observe the below code:

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: public B
{ };

class D: public B
{ };

class E
    : public C
    , public D
{ };

int main()
{
    E e;
    C &c = e;
    D &d = e;
    std::cout << c.get_c();
    d.set_c('b');
    std::cout << c.get_c() << std::endl;
    return 0;
}

O/P: aa I expect output would be ab. What would be the reason for getting "aa"??

If i have c.set_c('b') instead of d.set_c('b') then I will get O/P : "ab", Here also, I am not getting why is it as such. Both c, d are referring to one object only.

class C:virtual public B{};
class D:virtual public B{};

If the class C, class D are inherited virtually from B, then O/P would always be "ab"

like image 257
ranganath111 Avatar asked Oct 02 '12 18:10

ranganath111


2 Answers

There are two copies of B in E, one via C and one via D. When you call d.set_c('b'), you're modifying the m_c in D's B. When you call c.get_c(), you then get the m_c in C's B, which hasn't changed.

When you make C and D inherit from B virtually, it solves the problem, because then there's only one copy of B in E.

This is relevant: http://www.parashift.com/c++-faq/virtual-inheritance-where.html

like image 168
Stuart Golodetz Avatar answered Sep 30 '22 02:09

Stuart Golodetz


consider class C : public B and C* c = new C then c point to an storage that begin with a B since C* is also B*. and this is true for class D : public B.

Now for class E : public C, public D and E* e = new E(). memory of e is something like:

{| B of C | other members of C }{| B of D | other members of D}

as you can see in above case we have 2 instance of B one for C and another for D and now it is obvious when you call ((D*)e)->set_c( 'b' ) you only change B instance of D and B instance of C will remain unchanged.

now when you say class C : public virtual B, C++ share B instance with any other class that virtually inherit from B. so in this case e is something like:

           | shared B |
    | C members | | D members |

and as you can see we have only one B so calling ((C*)e)->set_c and ((D*)e)->set_c will both act on same B.

like image 39
BigBoss Avatar answered Sep 30 '22 01:09

BigBoss