【问题标题】:c++ public object change should invoke functionc++ 公共对象更改应该调用函数
【发布时间】:2012-08-25 07:34:12
【问题描述】:

我创建了一个这样的类

class myClass {

public:  
 int addMeOne; 
 void Invoked()  { .... }
};

我创建了它的一个对象,并通过引用将它发送到我程序的所有其他模块。每个人都习惯将 addMeOne 变量增加 1 。有些人甚至习惯添加两次,但这不是重点。

有了这个,现在我希望每当有人更改 addMeOne 时,我的函数 Invoked() 应该被调用。

请注意,正确的策略是我应该允许 addMeOne 被某个函数暴露在外部,而在该函数内部我可以调用 Invoked 。但是,现在无法更改接口,因为它现在已向所有其他人公开并且不应修改。我该如何纠正这个。 ?

【问题讨论】:

  • 你应该提供 getter 和 setter 方法来改变值然后调用你的回调。
  • 您可以通过引用包装器来做到这一点,但仅此而已。

标签: c++ function object invoke


【解决方案1】:

您必须创建一个将值分配给addMeOne 变量的方法,这称为setter 方法,并将变量本身设为私有。

我相信,在更改整数变量时无法触发函数。

更改接口但不会需要更改外部代码的另一种方法是定义一个模拟整数行为的类,即实现@ 987654322@等,把addMeOne改成这种类型。

【讨论】:

  • 请在投反对票时发表评论
  • 在您进行一系列(多次?)编辑之前,您的回答并没有解决问题所在。
  • @enderland 答案的一部分。 OP询问是否可以在不更改界面的情况下完成此操作,答案是否定的。
【解决方案2】:

您需要阅读有关封装的内容。如果不向 addMeOn 提供锁定的 getter / setter 接口,就无法保证对其使用的控制。

不要害怕改变界面。对于任何使用它来进行更改的人来说,这不是一项艰巨的任务,他们应该清楚您所做的更改是为他们的利益提供价值。

【讨论】:

    【解决方案3】:

    您应该保留此类的 ABI,还是只保留其客户使用的语法? 如果您可以更改addMeOne 的类型,保留编写addMeOne++ 等的能力,您可以为它定义一个类和相关的运算符——然后使addMeOne 成为这个类的一个实例。当然,现在addMeOne 运算符可以做任何事情——包括调用一些MyClass 成员函数。

    伪代码:

    class Proxy
    {
    public:
      Proxy(YourClass *parent) : parent_(parent), value_(0)
      {}
      void operator++() 
      {
        ++value_;
        // doAnything with parent_
      }
      // accessors, cast operators etc...
    private:
      YourClass *parent_;
      int value_;
    };
    
    class YourClass
    {
    public:
      YourClass() : addMeOne(this)
      {}
      Proxy addMeOne;
    };
    

    【讨论】:

      【解决方案4】:

      真的,告诉所有客户端使用方法而不是公共变量可能是值得的。您要么需要更改类、客户端或两者。

      没有办法解决它。再做一次,做对。接受打击。

      有一些技巧:一旦您公开了一个成员变量,您可以做的一件事就是将int addMeOne 替换为其他具有相同名称但类型不同的变量。 countedint addMeOne。您必须编写 countedint 类,使其行为类似于 int,但赋值、递增等也会计算它们的使用次数。例如

      countedint & operator ++(){
         m_value++;
         m_number_of_uses++;
         return *this;
      }
      countedint & operator --(){
         m_value--;
         m_number_of_uses++;
         return *this;
      }
      

      您可能还需要对 int 使用强制转换运算符,并且您也可以计算其中的使用次数。

      【讨论】:

        【解决方案5】:

        使用可以把addMeOne变成一个代理。

        class myClass 
        {
            class addMeOneProxy
            {
                public:
                    addMeOneProxy(myClass &s) : parent(s) {}
        
                    // This gets called whenever something tries to use the addMeOne 
                    // member variable as an integer.
                    operator int() const 
                    {
                        return parent.addMeOne;
                    }
        
                    // This gets called whenever something assigns a value to addMeOne.
                    int operator=(int val) 
                    {
                        parent.Invoked(); 
                        return val;
                    }
        
                    // You could also implement an operator++ or whatever else you need.
        
                private:
                    myClass &parent;
            };
        
          public:
            void Invoked();
            addMeOneProxy addMeOne;
        };
        

        当然,如果您决定在某个时候将 Invoked() 设为私有,则需要将 myClass 设为 addMeOneProxy 的朋友类,以便 addMeOneProxy 可以调用 Invoked 成员函数。

        我当然同意其他评论者的观点,即您确实应该为此拥有 getter 和 setter 函数,但我也理解开发人员通常无法控制和改变他们所生活的世界。因此,代理是您可以做到的如果你不能或被允许改变世界,那就去做吧。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-02-23
          • 1970-01-01
          • 2011-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多