gpt4 book ai didi

c++ - 无法将 "member pointer to derived class"转换为 "member pointer to base class"

转载 作者:可可西里 更新时间:2023-11-01 16:38:10 25 4
gpt4 key购买 nike

使用指向基类的指针调用类的虚成员函数当然是 C++ 中非常常见的事情。所以我觉得很奇怪,当你有一个成员指针而不是一个普通指针时,似乎不可能做同样的事情。请考虑以下代码:

struct B
{
virtual void f();
};

struct D : B
{
virtual void f();
};

struct E
{
B b;
D d;
};

int main()
{
E e;

// First with normal pointers:
B* pb1 = &e.b; // OK
B* pb2 = &e.d; // OK, B is a base of D
pb1->f(); // OK, calls B::f()
pb2->f(); // OK, calls D::f()

// Now with member pointers:
B E::* pmb1 = &E::b; // OK
B E::* pmb2 = &E::d; // Error: invalid conversion from ‘D E::*’ to ‘B E::*’
(e.*pmb1).f(); // OK, calls B::f()
(e.*pmb2).f(); // Why not call D::f() ???

return 0;
}

Visual C++ 继续说:

错误 C2440:“正在初始化”:无法从“D E::*”转换为“B E::*”
指向的类型是不相关的;转换需要 reinterpret_cast,C 风格的转换或函数风格的转换

我不明白为什么这些是“无关的”。为什么这不可能?


编辑:
我试图将此保留为 C++ 问题,而不是关于我要解决的特定问题,但这本质上是我想做的:

std::vector<B E::*> v;
v.push_back( &E::b ); // OK
v.push_back( &E::d ); // Error

B& g( E& e, int i )
{
return e.*v[i];
}

E 是一个类,包含几个派生自 B 的成员。 vector v 用于组织(例如重新排序)指向这些成员的成员指针。 vector v 很少变化。函数 g() 允许您使用 v 的索引来选择 E 的成员之一。它经常被调用,并且每次都使用不同的 E。

如果您考虑一下,v 只是一个偏移量查找表。函数 g() 只是选择这些偏移量之一并将其添加到 E* 以返回 B*。函数 g() 由编译器内联并编译为仅 4 条 CPU 指令,这正是我想要的:

// g( e, 1 )
mov rax,qword ptr [v (013F7F5798h)]
movsxd rcx,dword ptr [rax+4]
lea rax,[e]
add rcx,rax

我想不出标准不允许将 D E::* 转换为 B E::* 的任何原因。

最佳答案

简单的答案是,C++ 没有定义您正在尝试的转换,因此您的程序格式不正确。

考虑标准转换 (C++11§4/1):

Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions.

由于您没有执行任何转换,也没有定义任何自定义转换,因此您确实在执行此类标准转换。在不枚举所有可能的此类转换的情况下,您的示例有两种明确的兴趣:指针 转换和指向成员的指针 转换。请注意,C++ 不会将指向成员类型的指针视为指针类型的子集。

指向成员转换的指​​针在 C++11§4.11 中定义并且恰好包含两个转换:

  • 空成员指针转换允许将空指针常量转换为指向成员类型的指针 (4.11/1)。
  • 稍微做作的第二次转换 (4.11/2):

    “pointer to member of B of type cv T”, where B is a class type, can be converted to a [...] “pointer to member of D of type cv T”, where D is a derived class [...] of B

将此与上一节 4.10 进行对比,该节定义了三种指针转换:

  • 空指针转换 (4.10/1),允许将空指针常量转换为指针类型。
  • 转换为指向 void 的指针 (4.10/2),它允许将任何指针类型转换为指向 void 的指针。
  • 最后是为什么它使用指针(而不是指向成员的指针)(4.1​​0/3):

    A [...] “pointer to cv D”, where D is a class type, can be converted to a [...] “pointer to cv B”, where B is a base class [...] of D

因此,总结一下:您正在尝试的标准转换是为您的指针示例定义的,但对于指向成员变体的指针来说根本不存在。

关于c++ - 无法将 "member pointer to derived class"转换为 "member pointer to base class",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28156381/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com