Скажите, пожалуйста, почему вывод такой, как показано ниже для следующей программы. Я не получаю виртуальные классы в C ++. соблюдайте следующий код:
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: аа
Я ожидаю, что выход будет AB. Что было бы причиной для получения «аа» ??
Если у меня есть c.set_c (‘b’) вместо d.set_c (‘b’), тогда я получу O / P: «ab». Здесь также я не понимаю, почему это так. Оба c, d относятся только к одному объекту.
class C:virtual public B{};
class D:virtual public B{};
Если класс C, класс D унаследованы практически от B, то
O / P всегда будет «ab»
рассматривать class C : public B
а также C* c = new C
затем c
указать на хранилище, которое начинается с B
поскольку C*
это также B*
, а это true
за class D : public B
,
Теперь для class E : public C, public D
а также E* e = new E()
, память о e
это что-то вроде:
{| B of C | other members of C }{| B of D | other members of D}
как вы можете видеть в приведенном выше случае у нас есть 2 экземпляра B
один для C
и еще один для D
и теперь это очевидно, когда вы звоните ((D*)e)->set_c( 'b' )
ты только меняешься B
экземпляр D
а также B
экземпляр C
останется без изменений.
теперь, когда вы говорите class C : public virtual B
, C ++ поделиться B
экземпляр с любым другим классом, который практически наследует от B
, так что в этом случае e
это что-то вроде:
| shared B |
| C members | | D members |
и, как вы можете видеть, у нас есть только один B
так зовет ((C*)e)->set_c
а также ((D*)e)->set_c
оба будут действовать на то же B
,
Есть две копии B
в E
один через C
и один через D
, Когда вы звоните d.set_c('b')
модифицируешь m_c
в D
«s B
, Когда вы звоните c.get_c()
, тогда вы получите m_c
в C
«s B
, который не изменился.
Когда вы делаете C
а также D
наследовать от B
практически, это решает проблему, потому что тогда есть только одна копия B
в E
,
Это актуально: http://www.parashift.com/c++-faq/virtual-inheritance-where.html
Я не уверен, что понимаю проблему, но ваш вопрос содержит ответ, объявите B как виртуальную базу для C и D, и вы получите.
#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;
}
что приводит к желаемому результату, не так ли?
a
d
c