2

我有一个类,它具有访问器方法,这些访问器方法旨在在类之外用于查看它的一些私有数据。

但是,类的内部方法不应使用这些公共访问器,因为类的内部状态会被其其他方法更改,并且这些更改不会写入公共访问器查看的位置,直到计算完成。

是否有一种编译时方法可以防止类调用它自己的一个或多个成员?或者,使用运行时检查assert很好,因为它可以很容易地在发布编译中消除。

4

2 回答 2

2

虽然我在实践中从未见过这种模式,但您可以将实现和接口分开(尽管通常情况相反)

namespace detail {
    class Impl {
    protected:
        Impl() : x_(0) {}

        int x_;
        void internal() { x_ = 1; }
        void something_else() { x_ = 2; }
    };
}

class Interface : public detail::Impl {
public:
    int x() const { return x_; }
    void x(int x) { x_ = x; }
};

或者更进一步没有推导:

class Interface;

namespace detail {
    class Impl {
    private:
        friend class ::Interface;
        Impl() : x_(0) {}

        int x_;
        void internal() { x_ = 1; }
        void something_else() { x_ = 2; }
    };
}

class Interface {
public:
    int x() const { return impl_.x_; }
    void x(int x) { impl_.x_ = x; }
private:
    Impl impl_;
};

还要查找 PIMPL 惯用语,它通常用于减少头文件/库/客户端耦合并增加编译时间。

于 2013-01-26T13:05:42.213 回答
0

对于使用断言的调试构建,这是我的建议:

  • 制作一个简单的函数或一个名为IncrementInternalCallCount. 这将增加类内的调用计数。为此,只需在类中有一个计数器变量。仅将这些东西用于调试/诊断目的。
  • 在类的每个方法中调用这个宏/函数。除了那些 getter 函数。
  • 在 getter 函数中,检查 internal-call-count 是否大于零,如果是。提出断言。

为此,您可以使用一些 RAII 类,它会增加计数器,并会在函数退出时减少计数器。因此,您需要在每个函数的开头放置一个 RAII 对象。析构函数将被自动调用。这也将允许从其他类函数调用所有非 getter 函数。

非常少的代码(不是严格的 C++ 正确的):

class CYourClass
{
    int Counter = 0; // Not C++ syntax

   IncrementCallCounter() { Counter++;}
   DecrementCallCounter() { Counter++;}
   CheckCounterStatus() { if(Counter>0) ASSERT;}

private:
   void InternalFun() 
  {
     IncrementCallCounter();
    // Do work, call anything
    DecrementCallCounter();
  }

public:
int Getter1()
{
   CheckCounterStatus();
}
};
于 2013-01-26T12:59:41.983 回答