3

我有两节课:

class base
{
protected:
   int x;
};

class der: public base
{
   void Acc(base& b)
   {
      b.*(&der::x) = 5;
   }
};

以这种方式访问​​基本受保护成员是否安全 (&der::x) ?我担心它可能指向错误的变量。


这是通过访问基类对象的受保护成员的方式。

在此处输入图像描述

上面的代码:

在此处输入图像描述

4

5 回答 5

1

对于那些可能难以理解以下行的人

b.*(&der::x) = 5;

它可以写成:

b.*(&(der::x)) = 5;

由于范围解析运算符可以省略,因为我们只有一个x在基类和派生类中命名的变量。

b.*(&x) = 5;

这只不过是获取地址x然后再次取消引用它。它可以写成:

b.x = 5;

我希望你能意识到这一点。但是,如果您使用b.x而不是 'b.*(&der::x) = 5;',您的代码将无法编译 因为“x”是受保护的,这用于绕过阻止我们编写的编译器规则b.x = 5;

于 2013-08-08T04:20:25.713 回答
0

是的,它是安全的——但它有点奇怪,而且会让读者感到困惑。

于 2013-08-08T03:40:42.387 回答
0

首先不要把事情搞得太复杂。当你编译这段代码时,它永远不会编译。我会告诉你为什么这段代码很复杂,为什么它不能编译。

1> Why this code is complicated ?
According to the basic of c++ we can easily access the protected member of base 
class in drive class. So you can write you code like this.

类基{受保护:int x;} // 基类结束

类 der:公共基础 { void Acc() { x = 5; } }// der 类结束。

 2> Why this code will not compile ?

*(&der::x) = 5;

该语句是正确且可编译的,因为它将值放入继承后属于 der 类的 x 变量中。换句话说,我们可以说这种说法。

x = 5;

*(&der::x) = 5;

是等价的并且做同样的事情,但是如果你写一个像

b.(*(&der::x)) = 5;

它将产生错误,因为当您使用点运算符(。)来调用类的成员时,就在 (.) 之后,您必须指定类的成员。所以在上面的表达式中只有 x 是类 b 的成员,除了所有都会产生错误。

Conclusion, if code will not compile then how we can say it is safe or not. Code is
safe or not is depend on the resource utilization, which it will during runtime.
于 2013-08-08T05:35:43.737 回答
0

您正在做的是隐式转换,这与写作相同static_cast<der&>(b).x = 5;

只要您可以确定b参数始终是 type ,它就是安全的der。如果您使用派生自 的其他类型调用它会发生什么base?该类型可以x用于除der.

class nuclear_submarine: public base {};

void dostuff(der d)
{
   nuclear_submarine ns;
   d.Acc(ns); // *poff*
}
于 2013-08-08T07:18:14.547 回答
0

这种语法是绕过protected成员的访问规则来编译代码而不会出错的一种解决方法。在我们开始之前记住这一点:
class X方法中,我们可以访问它的所有成员(private, protected, public),而不管该成员属于this对象还是其他对象class X

再次考虑您的功能:

void Acc(base& b)
{
  x = 5;  // ok, because `x` is a protected member to `this` object
  b.x = 5;  // error, because `b` isn't part of `this` object
}

让我们以稍微混淆的方式编写上面的代码:

void Acc(base& b)
{
  this->(base::x) = 5;  // ok, because `x` is a protected member to `this` object
  b.(base::x) = 5;  // error, because `b` isn't part of `this` object
}

并且还增加了一层:

void Acc(base& b)
{
  this->*(&der::x) = 5;  // ok, because `x` is a protected member to `this` object
  b.*(&base::x) = 5;  // error, because `b` isn't part of `this` object
}

现在,如果您通过编写以下语句替换第二条语句:

b.*(&der::x) = 5;

编译得很好
实际上,它等价于b.x,但它绕过了阻止我们编写b.x = 5;.

但这样的陈述往往会导致未定义的行为。因为,想象一下如果b作为参考传递会发生什么some_other_derived_class_of_base!最好的办法是为xin引入访问方法class base

void base::set_x (int v) { x = v; }
于 2013-08-08T07:49:17.500 回答