gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 10:35:55 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++继续说:
error C2440: 'initializing' : cannot convert from 'D E::* ' to 'B E::* '
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

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

编辑:
我试图将其保留为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/60323143/

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