【问题标题】:C++ - Why don't const functions force const-ness on member-pointers?C++ - 为什么 const 函数不强制成员指针上的 const-ness?
【发布时间】:2012-04-03 13:13:32
【问题描述】:

Const 函数似乎并不关心您是否将成员指针解引用为非 const 引用。也可以返回非常量成员指针。但是,不允许返回具有值类型的数据成员的引用或地址。

为什么?

class Class
{
public:
unsigned int& value2(void) const
{
    *m_ptr = 10;
    return *m_ptr; 
    //Why?
}

unsigned int* value3(void) const
{
    return m_ptr; //Why?
}

private:
unsigned int* m_ptr;
};

【问题讨论】:

  • 你的意思是指向成员函数的指针?
  • 你应该提供一个让你担心的例子。从描述中很难知道。当您说 member-pointer 时,您是指作为指针的成员还是指向成员的指针
  • @NFRCR:您实际上是指(通过阅读代码)作为数据成员的指针。这就是为什么提供代码示例很重要。

标签: c++


【解决方案1】:

编辑:

关于您的代码:您永远不会真正更改成员或返回对它的引用。

unsigned int& value2(void) const
{
    *m_ptr = 10;
    return *m_ptr; 
                //Why?
}
//returns the value your member points to, not your member

unsigned int* value3(void) const
{
    return m_ptr; //Why?
}
//returns a copy of your member

我在 sn-p 中发布的版本是不允许的。

例如:

struct A
{
   int * x;
   int& getX() const { return *x; }
   int* getX1() const { return x; }
   int*& getX2() const { return x; } //error here
};

只有最后一个方法会返回错误,因为:

  • 第一个返回值,它不是 const。指针是 const。
  • 第二个返回指针按值,又没问题
  • 第三个实际上是通过引用返回成员,这就是为什么它是非法的

【讨论】:

  • 在我的程序中使用 const 时,我还是个新手。所以如果我错了请纠正我。从我在您的代码中看到的内容来看, x 是一个指向非常量整数的非常量指针。但是,在您关于第一个函数 int& getX() const {return *x;} 的观点中,您说指针是 const。如果我是对的,您需要删除该部分。
  • @batbrat 指针 is const,但它指向的不是。所以当你返回它的值*x你可以修改它。
  • 恐怕我还是不明白。 getX() 中的 this 指针是常量,但 x 本身被声明为非常量。如果您能进一步澄清,我将不胜感激。我也在阅读关于 const 正确性的内容,但我发现在这些问题上我从人类那里学到了更好的东西。
  • @batbrat 第一个函数返回对x 指向的整数的引用。你没有返回 x 本身,所以没有机会修改它。
  • 感谢您的解释。我终于明白了。非常感激! :)
【解决方案2】:

它确实强制了成员指针的常量;只是不是指针指向的常量!

为了证明,以下是非法的:

class foo
{
public:
    void bar() const
    {
        p = 0;
    }

private:
    int* p;
};

会给你一个编译错误,例如assignment of member 'foo::p' in read-only object

基本上在一个const成员函数中,T类型的成员变量被认为是T const,如果T是指针类型,比如说int*,这就产生int* const,意思是“const指针to int",即指针不可修改,但取消引用它会产生int&,而不是const int&。如果T*被认为是T const *T const * const,那就另当别论了。

至于基本原理,仅仅因为指针是对象状态的一部分,并不意味着指针指向的对象是(尽管它可以是)。更改指针指向的内容不会改变对象的可想象的状态

【讨论】:

    【解决方案3】:

    我想我不明白你的问题。我尝试了以下方法:

    class X {
      int x;
      int* foo() const {
        return &x;
      }
    };
    
    int main() {
    }
    

    它无法正确编译并显示消息“错误:从‘const int*’到‘int*’的无效转换”。

    您的问题是否与上述示例相符?如果不一样,能否给个示例代码?


    鉴于对您的问题的更详细解释,现在我理解您了。 成员指针 unsigned int* m_ptr 在 const 成员函数中是常量。但指针所指的内容——不是。该内容超出了您的对象的范围,并且 const 函数与它无关。

    在您的value2 函数中,您将无法更改指针本身。就是这样。

    【讨论】:

      【解决方案4】:

      我想这就是困扰你的原因。

      struct Example
      {
         int * p;
         Example(): i(new int) {}
         ~Example() { delete p; }
      };
      
      const Example e;
      *(e.i) = 7 
      

      这没关系,因为指针没有改变,它仍然指向内存中的同一个点。

      但是这并不好,因为它会改变指针:

      e.i = new int(4);
      

      如果你希望这两个都被禁止,你应该提供一个访问器函数。

      class Example
      {
        public:
          int * i() { return i_; }
          const int * i() const { return i_; }
        protected: 
          int i_;
      };
      

      现在我们有了:

      Example e1;
      *( e.i() )=7; //OK
      
      const Example e2;
      *( e.i() )=7; // FAILS TO COMPILE.
      

      【讨论】:

        【解决方案5】:

        常量函数确实尊重其成员变量的常量性。当您返回一个指向函数的指针时,您返回一个指针,您返回该指针的副本,出于同样的原因,您可以在 const 方法中返回对象的副本。然而,指针所指向的内容不会被视为 const,因此您甚至可以在 const 函数中对其进行修改。

        例如:

            struct A
            {
                int n;
                int * p;
                int & f1() const {return n;} //not allowed
                int f2() const {return n;} //allowed
                int * f3() const {return p;} //allowed
                int *& f4() const {return p;} //not allowed
                int & f5() const {return *p;} //allowed, because what p points to is not const
            };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-17
          • 2014-10-18
          • 2011-08-22
          • 1970-01-01
          • 2011-08-20
          • 2011-03-04
          • 1970-01-01
          相关资源
          最近更新 更多