vendredi 18 avril 2014

polymorphisme - c ++ classes virtuelles : interesting point - Stack Overflow


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"




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.




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




I'm not sure I understand the problem but your question contains the answer, declare B as a virtual base to both C and D and you get.


#include <iostream>

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;
};

// note virtual inheritance
class C: virtual public B
{ };

// note virtual inheritance
class D: virtual public B
{ };

class E
: public C
, public D
{ };

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

which results in the output you want , doesn't it ??


a
d
c


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"



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.



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



I'm not sure I understand the problem but your question contains the answer, declare B as a virtual base to both C and D and you get.


#include <iostream>

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;
};

// note virtual inheritance
class C: virtual public B
{ };

// note virtual inheritance
class D: virtual public B
{ };

class E
: public C
, public D
{ };

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

which results in the output you want , doesn't it ??


a
d
c

0 commentaires:

Enregistrer un commentaire