且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C ++:对不同派生类对象的基指针调用(派生的)成员函数

更新时间:2023-02-14 23:01:48

这是UB。

你甚至可以使用static_cast而不是可恶的C风格的cast,本身是相当合法的。但

You can even use static_cast instead of the odious C-style cast, and the cast itself is quite legal. But


[注意:尽管类B不需要包含原始成员,
动态类型的对象到成员是
dereferenced必须包含原始成员;见5.5。 -end note](5.2.9 12)

[Note: although class B need not contain the original member, the dynamic type of the object on which the pointer to member is dereferenced must contain the original member; see 5.5. —end note ] (5.2.9 12)

第一个操作数称为对象表达式,如果对象表达式的动态
类型不包含
指针指向的成员,行为未定义(5.5 4)

"The first operand is called the object expression. If the dynamic type of the object expression does not contain the member to which the pointer refers, the behavior is undefined" (5.5 4)

你可以从一个动态类型DerivedB的对象调用它。

I.e., you go undefined when you call it from an object of dynamic type DerivedB.

现在,随着脏的hacks走,它可能不是最糟糕的(比手动遍历vtables更好)是真的需要吗?如果你不需要任何动态数据,为什么在DerivedB上调用它? Base在库中,你不能重新定义它。回调也是库管理员,所以你必须有这个 typedef void(Base :: * SEL_SCHEDULE)(float); ,OK。但是为什么不能为B定义 doSomething ,并使指针指向它与DerivedB的实例耦合?您说

Now, as a dirty hacks goes, it's probably not the worst (better than the manual traversing of vtables), but is it really needed? If you don't need any dynamic data, why call it on DerivedB? Base is in the library, you cannot redefine it. Callback is librarian, too, so you have to have this typedef void (Base::*SEL_SCHEDULE)(float);, OK. But why can't you define doSomething for B and make pointer to it to couple with an instance of DerivedB? You say


doSomethingA不访问其任何成员变量或调用
成员函数。它访问静态成员并调用其他静态
函数

doSomethingA does not access any of its member variables or call member functions. It accesses static members and calls other static functions

但是你可以在 doSomethingB 。或者,如果你的回调从对象类型完全解开,并且你需要一个成员函数指针的唯一原因是符合库回调签名,你可以使你的实际回调非成员简单的老函数,行成员 - DoSomething(float dt){ReallyDoSomething(dt);} 的回调构象。

But you can do it in doSomethingB as well. Or, if your callbacks are completely uncoupled from object types, and the only reason you need a member function pointer is the conformance to the library callback signature, you can make your actual callbacks non-member plain old functions, and call them from one-line members-callback conformers like DoSomething(float dt) {ReallyDoSomething(dt);}.