- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
这是来自 C++11 标准 sec 12.7.4。这比较困惑。
B::B
不明确的?不应该只是打电话a.A::f
? 4 Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the class’s non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual function call uses an explicit class member access (5.2.5) and the object expression refers to the complete object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the behavior is undefined. [ Example:
struct V {
virtual void f();
virtual void g();
};
struct A : virtual V {
virtual void f();
};
struct B : virtual V {
virtual void g();
B(V*, A*);
};
struct D : A, B {
virtual void f();
virtual void g();
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
f(); // calls V::f, not A::f
g(); // calls B::g, not D::g
v->g(); // v is base of B, the call is well-defined, calls B::g
a->f(); // undefined behavior, a’s type not a base of B
}—end example ]
最佳答案
标准的那部分只是告诉你,当你构建一些“大”对象时 J
其基类层次结构包含多重继承,而您当前正坐在某个基子对象的构造函数中 H
,那么你只能使用 H
的多态性及其直接和间接基础子对象。不允许在该子层次结构之外使用任何多态性。
例如,考虑这个继承图(箭头从派生类指向基类)
假设我们正在构建一个类型为 J
的“大”对象。 .我们当前正在执行类 H
的构造函数.在 H
的构造函数中您可以享受红色椭圆内子层次结构的典型构造函数限制多态性。例如,您可以调用类型为 B
的基子对象的虚函数。 ,并且多态行为将在带圆圈的子层次结构内按预期工作(“按预期”意味着多态行为将在层次结构中低至 H
,但不会更低)。您也可以调用 A
的虚函数, E
, X
和其他落在红色椭圆内的子对象。
但是,如果您以某种方式访问椭圆外的层次结构并尝试在那里使用多态,则行为将变得未定义。例如,如果您以某种方式获得对 G
的访问权限来自 H
的构造函数的子对象并尝试调用 G
的虚函数- 行为未定义。调用 D
的虚函数也是如此。和 I
来自 H
的构造函数.
获得对“外部”子层次结构的这种访问的唯一方法是如果有人以某种方式将指针/引用传递给 G
子对象进入 H
的构造函数.因此在标准文本中引用了“显式类成员访问”(尽管它似乎过多)。
该标准将虚拟继承包含在示例中,以演示此规则的包容性。在上图中的基础子对象 X
由椭圆形内部的子层次结构和椭圆形外部的子层次结构共享。标准说可以调用X
的虚函数来自 H
的构造函数的子对象.
请注意,即使 D
的构造也适用此限制。 , G
和 I
子对象在H
构建之前已经完成开始了。
该规范的根源导致了实现多态机制的实际考虑。在实际实现中,VMT 指针作为数据字段被引入到层次结构中最基本的多态类的对象布局中。派生类不引入自己的 VMT 指针,它们只是为基类(可能还有更长的 VMT)引入的指针提供自己的特定值。
看一下标准中的示例。类(class)A
派生自类 V
.这意味着A
的VMT指针物理上属于V
子对象。 V
引入的对虚函数的所有调用通过 V
引入的 VMT 指针调度. IE。每当你打电话
pointer_to_A->f();
V *v_subobject = (V *) pointer_to_A; // go to V
vmt = v_subobject->vmt_ptr; // retrieve the table
vmt[index_for_f](); // call through the table
V
完全相同子对象也嵌入到
B
中.为了使构造函数限制的多态性正常工作,编译器会放置一个指向
B
的指针。的 VMT 转换成 VMT 指针存储在
V
(因为当
B
的构造函数处于事件状态时
V
子对象必须充当
B
的一部分)。
a->f(); // as in the example
B
的 VMT 指针存储在其
V
中子对象并将尝试调用
f()
通过那个 VMT。这显然毫无意义。 IE。具有
A
的虚拟方法通过
B
派送的 VMT 没有意义。行为未定义。
f
至
B
并这样做
#include <iostream>
struct V {
virtual void f() { std::cout << "V" << std::endl; }
};
struct A : virtual V {
virtual void f() { std::cout << "A" << std::endl; }
};
struct B : virtual V {
virtual void f() { std::cout << "B" << std::endl; }
B(V*, A*);
};
struct D : A, B {
virtual void f() {}
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
a->f(); // What `f()` is called here???
}
int main() {
D d;
}
A::f
在这里被称为?我尝试了几个编译器,它们实际上都调用了
B::f
!同时,
this
指针值
B::f
在这样的电话中接收完全是假的。
V
子对象在
A
之间共享和
B
子对象。如果没有虚拟继承,行为很可能会更可预测。然而,语言规范显然决定按照我在图中绘制的方式绘制线条:当您构建
H
时不允许您走出
H
的“沙箱”的子层次结构,无论使用什么继承类型。
关于C++ 构造函数 : why is this virtual function call not safe?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11377629/
进程虚拟机和系统虚拟机有什么区别? 我的猜测是,进程 VM 没有为该操作系统的整个应用程序提供一种操作系统,而是为某些特定应用程序提供环境。 系统虚拟机为操作系统提供了一个安装环境,就像 Virtua
我在成员函数的上下文中理解 virtual,例如 virtual void frob()。但它在类声明的上下文中意味着什么,例如 class Foo : public virtual Bar? 对于给
根据 react-virtualized 文档,“AutoSizer 组件装饰 React 元素并自动管理宽度和高度属性,以便装饰元素填充可用空间”。 建议通常是加上height: 100%;或 fl
根据 this类似 StackOverflow 问题和其他文章,默认情况下 C# 方法是“非虚拟的”,我认为这意味着您不能在派生类中覆盖它们。 如果那是真的,能否请您向我解释一下,在下面的示例中,我如
我有一个基类Media和几个派生类,即DVD、Book等...基类写成: class Media{ private: int id; string title;
我搜索了一些关于虚函数声明的帖子,相信 =0 在 virtual void test()=0; 是固定句法所以 virtual void test()=NULL; virtual void test(
我正在使用 RV 列表加载具有自定义格式的大型文档。它非常有效,但我遇到了以下两个问题: 我目前在 cellmeasurer 中设置了一个列表 based on this计算行的动态高度(宽度是固定的
我一直在努力制作 this react virtualized table example工作 & 开始严重怀疑我的理智。我创建了一个 react 应用程序,我只是想在 App.js 中使用以下内容呈
我在Windows 7 Pro计算机上安装了Windows Virtual PC和Windows XP Mode。运行XP模式会在Virtual PC上自动安装XP。我想创建第二台与第一台相同的虚拟P
我使用 Virtual PC 来创建新的环境来测试我的安装程序。但我一定是做错了什么,因为内部装有 Vista 或 XP 的 VPC 镜像占用了大约 15GB 的磁盘空间(包括安装在其中的 VS200
是否可以为 Ubuntu 虚拟机动态分配处理器和内存?例如。进程在主机系统上运行,导致处理器的使用率从 30%-70% 上下波动,这些进程还占用 8GB 内存中 3GB-7GB 之间的波动量,即 1G
我正在使用“react-virtualized”来创建一个表。在该表中,一些数据可能显示为 'Brian Vaughn1'。 .此表格单元格应具有 font-weight: bold并且只应呈现文本,
我正在使用“react-virtualized”来创建一个表。在该表中,一些数据可能显示为 'Brian Vaughn1'。 .此表格单元格应具有 font-weight: bold并且只应呈现文本,
我一直在努力理解一段这样的代码: class A { // some class definition } class B { public: virtual A *s
基于 http://en.wikipedia.org/wiki/Virtual_inheritance class Animal { ... }; // Two classes virtually i
我看到 C++ 中的某些函数被声明为 virtual const int getNumber(); 但是如果函数声明如下有什么区别呢? const virtual int getNumber(); 这
问题来自C++ faq。 http://www.parashift.com/c++-faq-lite/protected-virtuals.html 使用公共(public)重载虚拟的代码: clas
这个问题在这里已经有了答案: How is "=default" different from "{}" for default constructor and destructor? (3 个答案
virtual final 函数(final 在基类)是否有任何 vtable/virtual 成本? class B{ public: virtual void fFinal() final
我有一个只包含 exe 文件(没有源代码)的 hello 工具。 你好工具结构: bin helloBin.exe helloRoot.exe conanfile.py conanfile.py
我是一名优秀的程序员,十分优秀!