多重虚拟继承:为什么 class 方法没有歧义?
multiple virtual inheritance: why isn't the class method ambiguous?
我在一次在线测试中遇到了以下 c++ 代码。
#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;
}
代码输出 a2a3 但我不明白。为什么这个 运行 首先不是 class B 方法不明确?另外class E实际上不是继承的。
如果您尝试 e.get_c()
,那将是模棱两可的。
然而,C
和D
接口各只包含一个B
,彼此之间一无所知。
您正在通过 c
和 d
引用访问 C
和 D
class 的方法,没有歧义。试试这个
std::cout << e.C::get_c() << e.C::get_n() << std::endl;
std::cout << e.D::get_c() << e.D::get_n() << std::endl;
//line below will not compile because here access 'get_c' is ambiguous
//std::cout << e.get_c() << e.get_n() << std::endl;
在这里您将直接通过 e
实例访问 C
和 D
classes 的方法。现在最后一行由于调用 e.get_c()
而有歧义,您必须指定 C::
或 D::
前缀来解决有利于 C
或 D
的歧义方法。
std::cout << e.C::get_c() << e.get_n() << std::endl;
std::cout << e.D::get_c() << e.get_n() << std::endl;
注意:get_n() 前不需要加前缀,因为A
是一个虚拟基class,介于C
和[=13 之间=] 在继承树中。
由于 c
的类型为 C&
而 d
的类型为 D&
,因此没有歧义 - C
和 D
都具有一个 B
个子对象。
(c
和 d
字面上指的是 e
各自的子对象——它们不是指“e
,而是在不同的类型下”。 )
之所以输出是"a2a3"而不是"a2b3"或"a2a2"是因为A
是虚继承的,所以只有一个A
E
中的子对象,因此只有一个 n
成员。
C
和D
子对象各有一个B
子对象,d.set_c('b');
修改d
中的子对象,但不修改[=]中的子对象10=].
我在一次在线测试中遇到了以下 c++ 代码。
#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;
}
代码输出 a2a3 但我不明白。为什么这个 运行 首先不是 class B 方法不明确?另外class E实际上不是继承的。
如果您尝试 e.get_c()
,那将是模棱两可的。
然而,C
和D
接口各只包含一个B
,彼此之间一无所知。
您正在通过 c
和 d
引用访问 C
和 D
class 的方法,没有歧义。试试这个
std::cout << e.C::get_c() << e.C::get_n() << std::endl;
std::cout << e.D::get_c() << e.D::get_n() << std::endl;
//line below will not compile because here access 'get_c' is ambiguous
//std::cout << e.get_c() << e.get_n() << std::endl;
在这里您将直接通过 e
实例访问 C
和 D
classes 的方法。现在最后一行由于调用 e.get_c()
而有歧义,您必须指定 C::
或 D::
前缀来解决有利于 C
或 D
的歧义方法。
std::cout << e.C::get_c() << e.get_n() << std::endl;
std::cout << e.D::get_c() << e.get_n() << std::endl;
注意:get_n() 前不需要加前缀,因为A
是一个虚拟基class,介于C
和[=13 之间=] 在继承树中。
由于 c
的类型为 C&
而 d
的类型为 D&
,因此没有歧义 - C
和 D
都具有一个 B
个子对象。
(c
和 d
字面上指的是 e
各自的子对象——它们不是指“e
,而是在不同的类型下”。 )
之所以输出是"a2a3"而不是"a2b3"或"a2a2"是因为A
是虚继承的,所以只有一个A
E
中的子对象,因此只有一个 n
成员。
C
和D
子对象各有一个B
子对象,d.set_c('b');
修改d
中的子对象,但不修改[=]中的子对象10=].