gpt4 book ai didi

C++ 继承和成员函数指针

转载 作者:IT老高 更新时间:2023-10-28 14:00:02 28 4
gpt4 key购买 nike

在 C++ 中,成员函数指针可以用来指向派生(甚至是基)类成员吗?

编辑:也许一个例子会有所帮助。假设我们有三个类的层次结构XYZ,按照继承顺序。Y 因此有一个基类 X 和一个派生类 Z

现在我们可以为类Y定义一个成员函数指针p。这写成:

void (Y::*p)();

(为简单起见,我假设我们只对签名为 void f() 的函数感兴趣)

这个指针p现在可以用来指向类Y的成员函数。

那么这个问题(真的是两个问题)是:

  1. p可以用来指向派生类Z中的函数吗?
  2. p可以用来指向基类X中的函数吗?

最佳答案

C++03 标准,§4.11 2 Pointer to member conversions :

An rvalue of type “pointer to member of B of type cv T,” where B is a class type, can be converted to an rvalue of type “pointer to member of D of type cv T,” where D is a derived class (clause 10) of B. If B is an inaccessible (clause 11), ambiguous (10.2) or virtual (10.1) base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion refers to the same member as the pointer to member before the conversion took place, but it refers to the base class member as if it were a member of the derived class. The result refers to the member in D’s instance of B. Since the result has type “pointer to member of D of type cv T,” it can be dereferenced with a D object. The result is the same as if the pointer to member of B were dereferenced with the B sub-object of D. The null member pointer value is converted to the null member pointer value of the destination type. 52)

52)The rule for conversion of pointers to members (from pointer to member of base to pointer to member of derived) appears inverted compared to the rule for pointers to objects (from pointer to derived to pointer to base) (4.10, clause 10). This inversion is necessary to ensure type safety. Note that a pointer to member is not a pointer to object or a pointer to function and the rules for conversions of such pointers do not apply to pointers to members. In particular, a pointer to member cannot be converted to a void*.

简而言之,您可以将指向可访问的非虚拟基类的成员的指针转换为指向派生类成员的指针,只要该成员没有歧义。

class A {
public:
void foo();
};
class B : public A {};
class C {
public:
void bar();
};
class D {
public:
void baz();
};
class E : public A, public B, private C, public virtual D {
public:
typedef void (E::*member)();
};
class F:public E {
public:
void bam();
};
...
int main() {
E::member mbr;
mbr = &A::foo; // invalid: ambiguous; E's A or B's A?
mbr = &C::bar; // invalid: C is private
mbr = &D::baz; // invalid: D is virtual
mbr = &F::bam; // invalid: conversion isn't defined by the standard
...

另一个方向的转换(通过 static_cast )由 § 5.2.9 控制9:

An rvalue of type "pointer to member of D of type cv1 T" can be converted to an rvalue of type "pointer to member of B of type cv2 T", where B is a base class (clause 10 class.derived) of D, if a valid standard conversion from "pointer to member of B of type T" to "pointer to member of D of type T" exists (4.11 conv.mem), and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.11) The null member pointer value (4.11 conv.mem) is converted to the null member pointer value of the destination type. If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the result of the cast is undefined. [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 expr.mptr.oper.]

11) Function types (including those used in pointer to member function types) are never cv-qualified; see 8.3.5 dcl.fct.

简而言之,您可以从派生的 D::* 转换到基地B::*如果您可以从 B::* 转换到 D::* ,尽管您只能使用 B::*在 D 类型或 D 的后代对象上。

关于C++ 继承和成员函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60000/

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