【问题标题】:How to make inaccessible class variable如何使不可访问的类变量
【发布时间】:2015-09-25 19:51:30
【问题描述】:

我想知道是否可以在此类中使类变量不可访问?更改此变量值的唯一方法是通过类设置器。例如:

class foo
{
private:
    int m_var;
    bool m_isBig;
    void setVar(int a_var)
    {
        // do something before setting value, like emitting signal
        m_var = a_var;
    }
    void method()
    {
        int copy = m_var; // ok
        m_var = 5; // error!
        setVar(101); // ok
        doSomething();
    }
    void doSomething()
    {
        if(m_var > 5)
        { m_isBig = true; }
        else
        { m_isBig = false; }
    }
};

我知道我可以只使用 setter 和 getter 编写另一个类,但是我将无法访问类 foo 中的其他方法/变量(封装!)。我认为这可能是一个常见问题,并且可能有一些设计模式,但我找不到。

编辑: 我编辑了代码以明确我想在 setter 中做什么。

【问题讨论】:

  • 你可以通过创建另一个只有 setter 和 getter 的类来获得这个功能,然后让这个额外的类访问来自 foo 的方法/变量,你可以让 foo 将它声明为friend。我希望你甚至可以把它变成一个内部类,如果你真的想隐藏它,可能只在实现文件中定义。
  • 你为什么要这个?如果你有一个私人成员,你负责实施,那是什么意思?
  • 你的代码doesn't compile,你的意思是private:吗?
  • @πάνταῥεῖ 是的,已编辑。

标签: c++ setter getter access-specifier


【解决方案1】:

我不知道这种模式,但一种可能性是将成员包装在嵌套类中。我认为这也是更好的风格,因为创建新类型表达了该成员不仅仅是一个整数,而是具有独特行为的意图。

class foo {
    class MVar {
      public:
        MVar(foo* parent, int value = 0) : m_parent(parent), m_value(value) {}
        MVar& operator=(const MVar&) = delete; // disable assignment
        operator int() const { return m_var; }
        void set(int new_value) {
            // do something, possibly with m_parent
            // nested classes have access to the parent's private members
            m_value = new_value;
        }
      private:
        foo* m_parent;
        int m_value;
    } m_var;
    void method() {
        int copy = m_var; // ok
        m_var = 5;        // error
        MVar.set(101);    // ok
    }
};

这并不完全符合您的要求,因为 m_var 并不真的 具有 int 类型,但这是需要考虑的事情。

【讨论】:

  • 为什么是反向指针?为什么不用一个简单的值包装器围绕一个 int?
  • @TemplateRex 如果 OP 在设置变量时想要执行的操作需要调用父级上的方法。 OP 确实说了一些可能类似于此的内容(但问题并不完全清楚)。
  • 听起来太复杂了,m_var 是一个 int 包装器,他想要的只是将其设置为某个整数值。如果method() 需要其他上下文,那么它可以从foo 类中获取,但m_var 肯定没有用处
  • 让 MVar 成为 foo 的朋友比将指针传递给类 foo 更简单吗?
【解决方案2】:

您不能完全按照您在 C++ 中的要求进行操作。类中的所有变量对类中的所有方法都是可见的,无论它们是公共的还是私有的。

你想问自己的问题是:为什么一个类要对自己隐藏一些东西?类的接口是类的内部实现和它向外界提供的服务之间的边界。你要么在课内,要么在课外。

考虑到这一点,也许你的用例是写一个额外的类是合适的事情?

【讨论】:

    【解决方案3】:

    您可以将整数包装到一个特殊的类中,并且只定义setVar(),而不是采用int 的赋值运算符

    class M_type
    {
        int m_var;
    public:
        explicit M_type(int m) : m_var{m} {}
        operator int() const { return m_var; }
        void setVar(int a_var) { m_var = a_var; }
    };
    
    class foo 
    {
        M_type m_var;
        bool m_isBig;
    public:
        explicit foo(int m) : m_var{m} {};
    
        void method()
        {
            int copy = m_var; // OK, calls operator int()
            m_var = 5; // error, no operator=(int)
            m_var.setVar(101); // OK, calls setVar(int)
            doSomething();
        }
    
        void doSomething()
        {
            if(m_var > 5)
            { m_isBig = true; }
            else
            { m_isBig = false; }
        }    
    };
    

    确保为M_type 提供一个采用intexplicit 构造函数,并且只提供一个充当“getter”的隐式转换operator int()。如果您也将构造函数设为隐式,编译器生成的赋值 operator=(M_type const&) 将能够将参数 5 转换为 M_type

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-05
      • 1970-01-01
      • 1970-01-01
      • 2015-07-26
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      • 2017-08-11
      相关资源
      最近更新 更多