以这种方式访问​​Base保护成员是否安全?

时间:2013-08-08 03:36:24

标签: c++ xcode protected

我有两个班级:

class base
{
protected:
   int x;
};

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

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


这是通过访问基类对象的受保护成员来传递的方法。

enter image description here

以上代码:

enter image description here

5 个答案:

答案 0 :(得分:1)

对于那些可能会发现难以理解以下内容的人

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

可以写成:

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

由于我们在base和派生类中只有一个名为x的变量,因此可以省略作用域解析运算符。

b.*(&x) = 5;

这只是取x的地址,然后再解除引用它。它可以写成:

b.x = 5;

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

答案 1 :(得分:0)

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

答案 2 :(得分: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.
  

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

     

class der:public base {              void Acc(){                   x = 5;              }       } //课程结束。

 2> Why this code will not compile ?
  

*(& der :: x)= 5;

这个语句是正确的并且编译,因为它会将值放在x变量中    这是继承之后der类的一部分。换句话说,我们可以这么说    言。

  

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.

答案 3 :(得分:0)

你正在做的是隐式演员,与写static_cast<der&>(b).x = 5;

是一回事

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

class nuclear_submarine: public base {};

void dostuff(der d)
{
   nuclear_submarine ns;
   d.Acc(ns); // *poff*
}

答案 4 :(得分:0)

这种语法是通过绕过protected成员的访问规则来编译代码而没有错误的解决方法。在我们开始之前记住这一点:
class X方法中,我们可以访问其所有成员(privateprotectedpublic),无论该成员属于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;

compiles fine
实际上,它等同于b.x,但它绕过了编译器规则,阻止我们编写b.x = 5;

但是这种陈述通常会导致未定义的行为。因为,想象如果将b作为some_other_derived_class_of_base的引用传递会发生什么!最好的办法是在x

中引入class base的访问方法
void base::set_x (int v) { x = v; }