我在这一行遇到问题
std::cout << &X::a << std::endl;
这一行 print 1 应该打印 &X::a 的地址
这是我的代码
#include <iostream>
#include <string>
#include <iomanip>
class X
{
public:
int a;
void f(int b);
};
void X::f(int b)
{
std::cout << "the value of b is " << b << std::endl;
}
void add()
{
std::cout << "Hello this function hello" << std::endl;
}
int main()
{
void (*funcPtr)(void) = add;
funcPtr();
int X::*ptrnumber = &X::a;
void (X::*ptrfunction)(int) = &X::f;
X xobj;
xobj.*ptrnumber = 10;
std::cout << "the vslue of a is " << xobj.*ptrnumber << std::endl;
(xobj.*ptrfunction)(20);
std::cout << std::hex << &X::a << std::endl;
//std::cout << funcPtr << std::endl;
}
我用不同的编译器c++编译,但我有相同的输出
我显示了这个“M1Xi”的类型,我不知道这个数据类型
&X::f
和 &X::a
不是 指针。因为 f
和 a
都是 非静态 成员,所以它们是 成员指针,无论命名和语法相似性如何,它们的行为都与 指针 非常不同。
成员指针(无论是函数还是数据成员)并不代表地址。所以尝试打印它的地址是没有意义的。
因此,标准库中的
<<
和 std::ostream
也没有重载,这也需要成员指针。
但是,存在以
bool
作为参数的重载,并且可以将成员指针隐式转换为 bool
。如果成员指针具有空成员指针值,则结果为 false
,否则结果为 true
。使用默认设置 true
将打印为 1
。
表达式
&X::a
不是可以在普通地址中使用的地址。它是成员的相对地址。它只能与指向成员的指针一起使用。
指向成员的指针可以转换为其他指向成员的指针,并且仅在有约束的情况下。它们不能转换为其他类型的指针或 int。在这种情况下很难打印它们的值。
唯一可能的转换是布尔值,它的目的是查看它是否为空。因为指向成员的指针可以为 nullptr:
int X::*px = &X::a;
bool bx = px; std::cout << bx <<std::endl;
px = nullptr;
bool bn = px; std::cout << bn <<std::endl;
如果要打印指向成员的指针的地址,则必须使用对象取消引用它:
std::cout << std::hex << &(xobj.*(&X::a)) << std::endl;
正如您可能想象的那样,不可能使用取消引用 nullptr 来成员或使用 nullptr 作为对象地址的技巧,因为取消引用空指针是 UB。顺便说一句,这不是一个真正的问题,因为该标准对对象的布局几乎没有保证,因此这个相对地址本身没什么用处。