C ++:如何确保类成员变量只能在某个方法中修改

时间:2017-11-14 19:00:40

标签: c++ c++11 c++14

我在MacOS Sierra上使用带有clang的C ++ 14。我想按设计强制执行规则。以下是规则。

我班上有一个成员变量说:

unsigned int m_important_num;

我班上有4种方法。

fun1();
fun2();
fun3();
fun4();

目的:
我只希望fun2()能够更改m_important_num的值。

问题:
如果除fun2()以外的任何方法更改变量,是否可能使编译器出错? 一种可能的方法是声明const以某种方式授权fun2()来改变const变量?这是一个好的解决方案吗?或者他们是更好的解决方案?

次要问题:
尝试做这样的事情是错误的设计吗?

6 个答案:

答案 0 :(得分:10)

封装它。将m_important_num放在自己的类中。在现有类中聚合它。有一个吸气剂。然后将fun2()作为内部类的成员函数。

答案 1 :(得分:10)

排序,附加图层:

class S1 {
public:
    void fun2() { /*Modify m_important_num */ }
    unsigned int getImportantNum() const { return m_important_num;}
private:
    unsigned int m_important_num;
};
class S2 : private S1
{
public:
    void fun1();
    using S1::fun2; // or void fun2() {S1::fun2();}
    void fun3();
    void fun4();
};

正如Yakk评论的那样,如果func2需要访问S2成员,CRTP可以解决这个问题:

template <typename Derived>
class S1 {
public:
    void fun2() { asDerived().foo3(); /*Modify m_important_num */ }
    unsigned int getImportantNum() const { return m_important_num;}
private:
    Derived& asDerived() { return stataic_cast<Derived&>(*this); }
private:
    unsigned int m_important_num;
};
class S2 : private S1<S2>
{
    // friend class S1<S2>; // If required.
public:
    void fun1();
    using S1::fun2; // or void fun2() {S1::fun2();}
    void fun3();
    void fun4();
};

答案 2 :(得分:1)

如果您想阻止某个方法修改该类中的任何成员,您可以使用尾随的const标识符:

class something{
private:
  unsigned int var;

public:
  void fun1() const;
  void fun2();
  void fun3() const;
  void fun4() const;     
}

此处,只有fun2()才能修改变量。

答案 3 :(得分:1)

我对Jeffrey解决方案的一点变体(如果我理解正确的话):将变量放在内部类中并使其成为private;创建一个public getter并将func2() friend设置为内部类。

我的意思是

struct foo
 {
   int f1 () { return b0.getVal(); }; // you can read `val` everywhere
   void f2 () { b0.val = 42; }; // you can write `val` in f2()
   void f3 () { /* b0.val = 42; ERROR ! */ }; // but only in f2()

   class bar
    { 
      private: 
         int val = 24;

      public:
         int getVal () { return val; }

      friend void foo::f2 ();
    };

   bar b0;
 };

换句话说:friend是你的朋友。

答案 4 :(得分:1)

我知道有很多好的答案,但在你的问题中还有一个你可以提到的选项:

  

一种可能的方法是声明const以某种方式授权fun2()来改变const变量?

#include <iostream>

using uint = unsigned int;

class Test
{
    const uint num;

public:

    Test(uint _num)
        :
          num(_num)
    {}

    uint get_num() const
    {
        return num;
    }

    void can_change_num(uint _new_num)
    {
        uint& n(const_cast<uint&>(num));
        n = _new_num;
    }

    void cant_change_num(uint _new_num)
    {
//      num = _new_num; // Doesn't compile
    }

};

int main()
{
    Test t(1);

    std::cout << "Num is " << t.get_num() << "\n";

    t.can_change_num(10);

    std::cout << "Num is " << t.get_num() << "\n";

    return 0;
}

可生产

Num is 1
Num is 10

答案 5 :(得分:1)

您已经对主要问题得到了很多好的答案。我会尝试解决第二个问题。

  

尝试做这样的事情是错误的设计吗?

很难说你不了解你的设计。一般来说,在代码审查期间检测到的任何类似内容都会引发一个大红旗。在具有复杂逻辑/实现的大类的情况下,这种保护是有意义的。否则你为什么要加倍努力让你的代码变得更复杂?你寻求的事实可能表明你的课程变得无法管理。

我建议考虑将它拆分为具有更好定义逻辑的较小部分,您不必担心这些错误很容易发生。