是否有可能将一个对象转发给一个没有在C++中定义额外变量或vtable的子类?

Eon*_*nil 9 c++ downcast

是否有可能将对象向下转换为子类并不定义任何额外的变量或虚方法?

如果我有这些课程,

class A { public: A (); };
class B : public A { public: void method1 () {} B (); };
Run Code Online (Sandbox Code Playgroud)

这是(1)可能和(2)标准安全吗?

A* a = new A ();
B* b = (B*)a;
b->method1();
Run Code Online (Sandbox Code Playgroud)

Ste*_*sop 6

指针转换充当a static_cast.5.2.9/2说,

如果[ A] 类型的对象实际上是[ ] 类型的对象的子对象B,则结果引用类型为[ B] 的封闭对象.否则,演员的结果是未定的.

您的对象不是对象的子B对象,因此结果未定义.

即使你这样做reinterpret_cast,通过结果指针访问对象的值也有未定义的行为,因为它违反了严格的别名.在C++ 11标准中,3.10/10:

如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

"不添加数据成员或虚拟成员函数的对象的动态类型的派生类" 不在下面的列表中.

根据method1实际情况,可能会在调用时避免访问对象的存储值.但我不确定它是否有可能.除非在标准的其他地方另有说明,否则为安全起见,假设调用非静态成员函数本身"访问对象的存储值",即使该函数实际上不使用任何数据成员.

这是那些可能在所有时间或几乎所有时间都可能在实践中起作用的尴尬案例之一.但它并不能保证,所以即使它看起来有效并且发出的代码看起来还不错,你也会担心有一天新的优化会破坏它.

一旦定义,C++类将关闭新成员,包括新成员函数.所以你创建的对象new A()具有它将拥有的所有成员函数.只需编写一个非成员函数 - 除非Aprotected成员,它将具有与A您的成员函数完全相同的访问权限.如果A确实有protected成员,那么就有一种从中获取的批准方式,您应该使用它来创建适当的实例B.

如果成员函数语法对您来说意义重大,那么根据A您可能能够编写的类:

B b = *a;    // "copy" the object (give B a suitable ctor)
b.method1(); // act on it
*a = b;      // copy it back (A needs copy assignment operator)
Run Code Online (Sandbox Code Playgroud)

显然这里有一些问题可能会阻止它工作:首先是对象是可复制的,还是线程安全的,以及是否method1存储指针/引用到b某个地方,一旦b被破坏就会开始悬挂.在C++ 11中,副本也许可以提高效率,但即便如此,我希望你会同意你必须跳过使用成员函数语法的箍是不值得的.

  • 关于你的最后一个代码,一个更方便的方法是使`B`成为`A`的包装器:而不是将对象复制到`b`中,`b`将保留一个引用/指向`a`,并作用于它.这是一种相当常见的模式. (2认同)

You*_*usf 5

  1. 对的,这是可能的。
  2. 不,按照标准来说是不安全的;它被气馁了。

这更像是 C void* 转换,这不是 C++ 中最好的做法。但我这样做了很多次而且效果很好。