我认为很简单,如果 BaseT 是 DerivedT 的基类,则可以将“指向类型为 DerivedT 的类 T 的成员的指针”用作“指向类型为 BaseT 的类 T 的成员的指针”。类比似乎至少对我来说是显而易见的,因为 DerivedT* 可以用作 BaseT*,因此 DerivedT T::* 应该能够用作 BaseT T::*
但事实并非如此:
struct BaseT
{
};
struct DerivedT: public BaseT
{
};
struct T
{
DerivedT m_test;
};
using BaseTMemPtr = BaseT T::*;
int main()
{
T test;
BaseT* simplePtr = &test.m_test; //It is DerivedT*, but can be used as BaseT*
BaseT (T::*memPtr) = &T::m_test; //Error, BaseT T::* cannot be used as DerivedT T::*
BaseTMemPtr memPtr2 = &T::m_test; //Error, just the same
}
正如我所见,有两种方法可以解释指向类成员的指针:所以这两种方式的主要区别在于,第一种可以解释为一种 DerivedT 指针(启用多态性),而后一种则丢弃类型并限制使用很多。
为什么 C++ 选择了第二种方法?启用使用 DerivedT T::* 作为 BaseT T::* 会产生什么不良后果?在实践中指向成员的指针是什么?
更新:
我想实现以下目标:
Desired solution
但如果成员不是 BaseMember 类型而是 BaseMember 后代,则它不起作用。
如果我使用 BaseMembers(但在这种情况下我无法实现所需的成员功能),则该概念有效:
Works with broken functionality
更新 2:为什么
TLDR:
一种编译时“标记”(唯一标识)运行时构造类的非静态成员对象的方法。然后检查常规(非成员)指针是否在具有编译时标记的运行时函数中
1、标记成员的编译时数组(可以是任何东西,在我看来是多态的成员指针)
2.包含对象的'this'指针(具有标记和未标记的成员)
3、常规(non-pointer-to-member)指向非静态成员对象的指针。
时间轴:类定义(编译时)-> 添加类成员(编译时)-> 将类成员标记为已启用-例如在数组中-(编译时)-> 构造(运行时)-> 成员将调用注册函数(运行时)-> 在注册函数中,我们需要检查是否允许调用者(我们将其作为常规指针接收)调用它功能与否(运行时)。
详细说明:
在一个库中,我有一个 CRTP 基类(DataBinding),如果用户想使用它的编译和运行时功能,他们应该继承它。
然后在库中我还有一个接口(interface)类:BaseMember,以及它的许多派生类。最终用户可以使用派生类在其用户定义的 DataBinding 后代类中添加非静态类成员对象。
在用户代码中,在 DataBinding 后代用户类中,用户可以拥有基于 BaseMember 的非静态类成员。这里出现了需要成员指针多态性的新功能:用户应该能够在编译时标记一些基于 BaseMember 的类成员(!)(类本身没有 constexpr 构造函数) - 在我看来这'mark' 可以存储指向 BaseMember 后代成员对象的成员的指针 - 并且只有被标记的对象应该被允许运行时调用 DataBinding(当前类的 CRTP 基类)中的类成员函数(registerMember)。
在 registerMember 运行时函数中,我有“this”对象指针(包含对象),我有编译时用户定义的列表,该列表标记了启用的成员指针(它可以用任何类型的唯一标识替换),并且我有实际的成员指针。我需要检查是否允许实际成员指针调用该函数(它被标记为编译时)。
最佳答案
指向数据成员的指针通常由一个简单的整数值表示,告诉所有者类的开头到成员开头的偏移量。因此,在给定指向其所有者的指针的情况下检索数据成员的算法就像“将偏移量添加到地址并取消引用”一样简单。
然而,为了从指向派生的指针到指向基的指针,这样简单的描述是不够的。由于虚拟继承,偏移量不一定是恒定的。为了找到偏移量,我们需要一个实际的派生对象。偏移量存储在某处。因此,在一般情况下,指向数据成员的指针必须表示为至少两个偏移量的组合,并且获取成员需要做出决定(是否存在虚拟基?)
我想标准本可以只为非虚拟继承情况提供这种转换。在这种情况下,偏移量是恒定的,转换将包括添加两个偏移量(除非我错过了其他一些极端情况)。然而,这并没有完成,原因当然是没有人觉得有足够的动力来写一份提案。指向数据成员的指针(与指向成员函数的指针相反)最初被 Stroustrup 认为是“泛化的产物,而不是真正有用的东西”(D&E,13.11 指向成员的指针)。它们现在(主要)用于以独立于实现的方式描述类布局,但实际上没有必要以多态方式使用它们。
关于c++ - 了解指向类型类成员的指针 - 无多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69593587/