通过限定名称访问成员数据的地址会产生错误



正如我们所知,派生类publicprotected成员的直接或间接基类在该派生类中可用。

所以我有一个例子:

struct Foo{int x_ = 10;};
struct Bar : Foo{};
struct FooBar : Bar{
void f()const{
std::cout << &x_ << " : " << x_ << 'n';
std::cout << &Foo::x_ << " : " << Foo::x_ << 'n';
std::cout << &Bar::x_ << " : " << Bar::x_ << 'n';
std::cout << &FooBar::x_ << " : " << FooBar::x_ << 'n';
}
};

int main(){
FooBar fb{};
fb.f();
}
  • 当我编译并运行程序时,我会得到输出:

    0x7ffc2f7ca878 : 10
    1 : 10
    1 : 10
    1 : 10
    

那么,为什么通过完全限定名称访问成员数据CCD_;无效的";住址但是直接访问(非限定查找(是可以的

  • 我的程序是否处于未定义行为?

  • 我已经使用GCC和CLANG编译了我的程序。

首先,很可能您不打算在每个std::cout语句中重复&运算符,所以我删除了每个重复的实例,以打印成员的值,而不是其地址。

现在看这个:

#include <iostream>
struct Foo{int x_ = 10;};
struct Bar : Foo{};
struct FooBar : Bar
{
void f()const
{
std::cout << &x_ << " : " << x_ << 'n';
std::cout << &(Foo::x_) << " : " << Foo::x_ << 'n';
std::cout << &(Bar::x_) << " : " << Bar::x_ << 'n';
std::cout << &(FooBar::x_) << " : " << FooBar::x_ << 'n';
}
};
int main(){
FooBar fb{};
fb.f();
}

输出:

0x7fffe136c594:10
0x7fffe336c594:10
0x7 fffe136C594:10
0x7ff fe136c594.10

一切都很好!我所做的改变是将Foo::x_这样的表达式放在括号中。为什么?由于&Foo::x_使用运算符的内置地址,请参阅cppreference.com中的Member访问运算符。它的值是指向数据成员的<strong]指针,而不是普通指针,因为它需要绑定到对象才能返回地址。另请参阅类似的stackoverflow问题以获得更多解释。>

编辑

您可能想知道为什么std::cout为指向成员指针的指针显示1。这是因为隐式转换为bool:

布尔转换
整型、浮点型、无范围枚举型、指针型和指向成员类型的指针型的prvalue可以转换为布尔类型的prvalue。

报价源

转换后的值当然是true,因为指针是有效的,并且只有nullptr(和0(转换为false。根据其他规则,true被转换为1。Q.E.D.

我的程序是否处于未定义行为?

否。行为是明确的。

那么,为什么通过完全限定名称访问成员数据A::x_的地址会产生一个";无效的";住址

您没有使用完全限定的名称。完全限定的名称总是从全局命名空间开始。例如,::Foo::x_将是一个完全限定的名称,而Foo::x_则不是。

你也不是";访问";成员(插入x_时除外(。在成员名称上应用一元运算符&时,结果是指向数据成员的指针。在&Foo::x_的情况下,类型将是int Foo::*,即指向类型为intFoo的成员的指针。

此外,1不一定是"1";无效";地址,但你观察到的根本不是地址。字符流没有接受指向数据成员的指针的流插入运算符。然而,它们确实有一个接受bool的重载,并且指向数据成员的所有指针都可以隐式转换为bool,因此这种重载是重载解决方案的有效候选者。

由于指向有问题的数据成员的指针不是null,因此转换后的值为true。当在字符流中插入true时,输出为1。

相关内容

  • 没有找到相关文章

最新更新