无法将“成员指针指向派生类"转换为“指向基类的成员指针";

编程入门 行业动态 更新时间:2024-10-24 20:23:27
本文介绍了无法将“成员指针指向派生类"转换为“指向基类的成员指针";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

使用指向基类的指针来调用类的虚拟成员函数当然是C ++中非常常见的事情.因此,我感到奇怪的是,当您拥有成员指针而不是普通指针时,似乎不可能做同样的事情.请考虑以下代码:

Calling virtual member functions of a class using a pointer to the base class is of course a very common thing to do in C++. So I find it strange that it seems impossible to do the same thing when you have a member pointer instead of a normal pointer. Please consider the following code:

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 ++继续说:

Visual C++ goes on to say:

错误C2440:正在初始化":无法从"D E :: *"转换为"B E :: *"指向的类型无关.转换需要reinterpret_cast,C样式转换或函数样式转换

我不明白为什么这些不相关".为什么这不可能呢?

I don't understand why these are 'unrelated'. Why is this not possible?

修改: 我试图将其保留为C ++问题,而不是我要解决的特定问题,但这实际上是我想做的事情:

I am trying to keep this a C++ question and not about the particular problem I am trying to solve, but this is essentially what I want to do:

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的成员.向量v用于组织(例如重新排序)指向这些成员的成员指针.向量v很少更改.函数g()允许您使用v的索引来选择E的成员之一.它经常被调用,每次使用不同的E进行调用.

E is a class containing several members derived from B. The vector v is used to organize (eg reorder) member pointers to these members. Vector v changes infrequently. The function g() allows you to select one of the members of E using an index into v. It is called very often and each time with a different E.

考虑一下,v只是偏移量的查找表.函数g()只需选择这些偏移量之一,然后将其添加到E *中即可返回B *.函数g()由编译器内联,仅编译为4条CPU指令,这正是我想要的:

If you think about it, v is just a lookup table of offsets. The function g() simply selects one of these offsets and add it to the E* in order to return the B*. The function g() is inlined by the compiler and compiles to just 4 CPU instructions, which is exactly what I want:

// 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 :: *的任何原因.

I cannot think of any reason why the standard would not allow a D E::* to be converted to a B E::*.

推荐答案

简单的答案是,C ++没有定义您尝试的转换,因此程序格式错误.

The simple answer, is that C++ does not define the conversion you are attempting and thus your program is ill formed.

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

Consider standard conversions (C++11§4/1):

标准转换是具有内置含义的隐式转换.第4章列举了此类转换的全部内容.

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

由于您没有执行任何强制转换,也没有定义任何自定义转换,因此实际上您正在执行这种标准转换.在没有列举所有可能的此类转换的情况下,您的示例明确涉及了两个: pointer 转换和 pointer to member 转换.请注意,C ++并不将指向成员类型的指针视为指针类型的子集.

Since you are not performing any cast, nor do you have any custom conversions defined, you are indeed performing such a standard conversion. Without enumerating all possible such conversions, two are of explicit interest for your example: pointer conversions and pointer to member conversions. Note that C++ does not consider pointer to member types to be a subset of pointer types.

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

Pointer to member conversions are defined in C++11§4.11 and consist of exactly two conversions:

  • 空成员指针转换,它允许将空指针常量转换为指向成员类型(4.11/1)的指针.
  • 人为设计的第二转换(4.11/2):

    • The null member pointer conversion which allows null pointer constants to be converted to pointer to member types (4.11/1).
    • The somewhat more contrived second conversion (4.11/2):

      指向cv T类型的B的成员的指针",其中B是类类型,可以转换为指向cv T类型的D的成员的指针",其中D是派生类[...] of B

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

        • The null pointer conversion (4.10/1) which allows null pointer constants to be converted to pointer types.
        • Conversion to pointers to void (4.10/2) which allows the conversion of any pointer type to pointer to void.
        • And finally why it works with pointers (but not pointers to member) (4.10/3):

          其中D是类类型的[[cv​​ D的指针],可以转换为[cv B的指针],其中B是基类[...]D的]

更多推荐

无法将“成员指针指向派生类"转换为“指向基类的成员指针";

本文发布于:2023-07-28 02:42:16,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1226552.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针   成员   转换为   派生类   quot

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!