- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在执行某项任务时遇到了问题,这是一个练习,而不是一个真正的程序。任务是定义结构 D 的复制构造函数,其行为方式与编译器生成的复制构造函数完全相同。
class Ob{
};
struct A {
Ob a;
};
struct B : A {
Ob b;
};
struct C : A, B {
Ob c;
};
struct D : C, A {
Ob d;
};
如您所见,结构 A 在结构 D 中间接派生了几次,这导致了复制构造函数定义中的歧义,如下所示:
D(const D& _d) : C(_d), A(_d), d(_d.d) {}
我的问题是如何正确定义复制构造函数?没有上述定义的代码编译通过,所以看起来应该是可以的。
MinGW 4.8.1 错误信息:
zad3.cpp:12:8: warning: direct base 'A' inaccessible in 'C' due to ambiguity [enabled by default]
struct C : A, B {
^
zad3.cpp:16:8: warning: direct base 'A' inaccessible in 'D' due to ambiguity [enabled by default]
struct D : C, A {
^
zad3.cpp: In copy constructor 'D::D(const D&)':
zad3.cpp:17:38: error: 'A' is an ambiguous base of 'D'
D(const D& _d) : C(_d), A(_d), d(_d.d) {}
^
重要提示:这是不是重复问题“Inaccessible direct base caused by multiple inheritance”,这是关于具有不同访问说明符的公共(public)基类,最终是由转换问题引起的。这里是关于消除以相同的可见性多次继承的公共(public)基类的必需初始化器的歧义。
最佳答案
注意:答案经过根本性编辑!
问题分析:
您正在使用 multiple inheritance with a diamond problem .
更具体地说,您的结构 D
继承相同的基类 A
三次:一次直接(struct D: C,A
)和两次间接(通过 C 的继承)。由于基类不是虚拟的,因此 D 有 3 个不同的 A 子对象。C++11 标准部分 10.1/4-5 称其为格子:
通常,您随后会通过显式限定来消除每个 A
的成员的歧义,告诉编译器您指的是 3 个 A
子对象中的哪一个。 C++11 第 10.1/5 节对此进行了解释。成员的语法应该是 A::a
, C::a
和 B::a
在 D< 范围内
,如果您在外面,每个最终都以 D::
开头。
不幸的是,C++11 section 10.2/5-6 中的成员名称查找逻辑确保直接 A
基总是使其他间接 A
基础不明确,尽管有明确的限定(甚至 using
语句)。
最终解决方案:
由于问题是由直接基类引起的,而且事实上没有办法区分这个与其他类的歧义,唯一真正有效的解决方案是使用一个空的中间类来强制使用不同的名称:
struct Ob{ int v; }; // v aded here to allow verification of copy of all members
struct A { Ob a; };
struct B : A { Ob b; };
struct A1 : A {}; // intermediary class just for diambiguation of A in C
struct C : A1, B { Ob c; }; // use A1 instead of A
struct A2 : A { }; // intermediary class just for diambiguation of A in D
struct D : C, A2 { // use A2 instead of A
Ob d;
D() { }
D(const D& _d) : C(_d), A2(_d), d(_d.d) { }
};
int main(int ac, char**av)
{
cout << "Multiple inheritance\n";
D x;
x.A2::a.v = 1; // without A2:: it's ambiguous
x.A1::a.v = 2; // without A1:: it's ambiguous
x.B::a.v = 3;
x.b.v = 4;
x.d.v = 5;
D y = x;
cout << "The moment of truth: if not 1 2 3 4 5, there's a problem!\n";
cout << y.A2::a.v << endl;
cout << y.A1::a.v << endl;
cout << y.B::a.v << endl;
cout << y.b.v << endl;
cout << y.d.v << endl;
}
此代码编译并使用 MSVC2013、clang 3.4.1 和 gcc 4.9。
其他(非)解决方案:
我之前的回答仅基于明确的限定条件。尽管有很多批评,但我真的在 MSVC2013 上编译和测试成功了!然而,它们是一件奇怪的事情:在编辑器中,intelisence 突出了一个歧义,但编译运行良好,没有任何错误。我最初认为这是一个智能错误,但现在意识到这是一个编译器不合规性(错误?)
提示D(const D& other) : C(other), A((const B)other), d(other.d)
的答案编译通过,但没有通过测试。为什么 ?因为 A((const B)other)
会将 other
理解为 B
。因此 D
中的 A
将使用间接继承自 B
的 A
的值进行初始化(所以另一个A
)。这是一个极其严重的错误,我花了一段时间才注意到。
当然你可以使用虚基类。那么D中就只有一个A
子对象了,解决了很多问题。但是我不知道你在设计什么,有些设计需要一个格子而不是一个虚拟的菱形。
如果你能负担得起两步复制(第 1 步:基的默认初始化;第 2 步:复制基上的目标值),当然有一些方法使用无歧义的成员函数返回正确基的引用。但这可能比上面介绍的简单解决方案更棘手且更容易出错。
关于c++ - 多重继承引起的C++拷贝构造函数调用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26832200/
我在 linux 上工作。我对windows没有太多想法。 windows中文件的权限是如何组织的?我们在unix中是否有像chmod这样的api来更改权限? 最佳答案 对于 Windows,有一个名
应用程序编程接口(interface) (API) 是一组用于访问基于 Web 的软件应用程序的编程指令和标准。 如果出现 ,有人可以向我解释一下吗?谷歌地图 或 优酷 这是API哪个是softwar
我有两个应用程序,A 和 B,它们使用 android 库 C。B 有一个服务 A 想通过 C 使用,例如 在我的库中有一个类试图将它绑定(bind)到服务,
我正在正常或安全模式下启动相机应用程序,具体取决于使用我的应用程序执行的手势,但一旦用户选择应用程序并点击始终,则没有选项可以更改默认值,即使是从 Android 的设置菜单中也是如此. camera
我有一个数据集,本质上是一个稀疏二进制矩阵,表示两个集合的元素之间的关系。例如,让第一组是人(用他们的名字表示),例如像这样的东西: people = set(['john','jane','mike
何为pythonic? pythonic如果翻译成中文的话就是很python。很+名词结构的用法在中国不少,比如:很娘,很国足,很CCTV等等。 我的理解为,很+名词表达了一种特殊和强调的意味。
某些 Prolog 目标的确定性成功问题已经一次又一次地出现在 - 至少 - 以下问题: Reification of term equality/inequality Intersection an
我指的是 DateTime.TryParse(string s, out DateTime result) 重载,它尝试从字符串中解析 DateTime - 没有特定的格式正在指定。 我可以从http
2020 年 04 月 10 日,《中共中央国务院关于构建更加完善的要素市场化配置体制机制的意见》正式公布,将数据确立为五大生产要素(土地、资本、劳动力以及技术)之
有人可以解释一下 NSNotification 的 addObserver 函数中 notificationSender 的用途吗? 这是 Apple 文档的解释: notificationSende
我是一名优秀的程序员,十分优秀!