c++ - 如何重构多余的 getter/setter 方法?

标签 c++ templates

我有一个现有的类,其中包含互斥锁保护的成员,如下所示(类 MembersNeedThreadSafe)...

// Just fake a mutex guard interface.  Obviously doesn't do anything
class Mutex
{
  public:
    struct Guard
    {
      Guard(Mutex & M) { };
    };
};

// This is the class I want to redesign.
class MembersNeedThreadSafe {
  Mutex M;

  int i;
  double k;
  // And a dozen more variables

  public:
  void SetI (int foo) { Mutex::Guard G(M); i = foo; }
  int GetI (void) { Mutex::Guard G(M); return i; }

  void SetK (double foo) { Mutex::Guard G(M); k = foo; }
  double GetK (void) { Mutex::Guard G(M); return k; }
  // And two dozen more methods
};

int main (void) {
  MembersNeedThreadSafe bar;

  bar.SetI(5);
  bar.SetK(6.0);

  double d = bar.GetK();

  return 0;
}

我想将MembersNeedThreadSafe类重构为更像这样的设计,但它无法编译,提示非静态数据成员的无效使用。

template <typename T, Mutex & M> class LockedVar {
  typedef LockedVar<T, M> my_type;
  T value;

  public:
  void Set(T const & foo) { Mutex::Guard G(M); value = foo; }
  T const & Get (void) { Mutex::Guard G(M); return value; }
};

// I want the class to look like this...
class MembersNeedThreadSafe {
  Mutex M;

  public:
  LockedVar <int, M> i;
  LockedVar <double, M> k;
  // And a dozen more variables
};

// This allows the code to run.
int main (void) {
  MembersNeedThreadSafe bar;

  bar.i.Set(5);
  bar.k.Set(6.0);

  double d = bar.k.Get();

  return 0;
}

那么...如何重构第一个代码块的 MembersNeedThreadSafe 类,这样我就不必为每个成员编写冗余的 getter 和 setter 方法?

附录: 我知道我可以使用这样的设计...

template <typename T> class LockedVar {
  typedef LockedVar<T> my_type;
  T value;
  Mutex & M;

  public:
  LockedVar (Mutex & foo) : M(foo) { }
  void Set(T const & foo) { Mutex::Guard G(M); value = foo; }
  T const & Get (void) { Mutex::Guard G(M); return value; }
};

但是当我这样做时,我的编译器(gcc 4.8.2)中的 sizeof(int) == 4,而 sizeof(LockedVar) == 16,这给我带来了一种危险信号。看来我应该能够通过使用互斥体作为模板参数来解决这个问题,并且我想知道如果可能的话如何做到这一点。

最佳答案

另一个选择是稍微修改一下LockedVar:

template <typename T> class LockedVar {
  typedef LockedVar<T> my_type;
  T value;

  public:

  void Set(T const & foo, Mutex & M ) { Mutex::Guard G(M); value = foo; }
  T const & Get (Mutex & M) { Mutex::Guard G(M); return value; }
};

此外,如果您一遍又一遍地重复该内容,尽管它可能看起来不太好看,但您可以创建一个宏:

#define IMPL_SET_GET( t, x ) \
    t x; \
    void Set##x (int foo) { Mutex::Guard G(M); x = foo; } \
    int Get##x (void) { Mutex::Guard G(M); return x; }

// This is the class I want to redesign.
class MembersNeedThreadSafe {
  Mutex M;


  // And a dozen more variables

  public:
      IMPL_SET_GET( int, i );
      IMPL_SET_GET( int, k );

  // And two dozen more methods
};

关于c++ - 如何重构多余的 getter/setter 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24013702/

相关文章:

c++ - 排序 vector ,未在此范围内声明顺序(库?)

php - 简单的 PHP : unable to execute C++ from php

c++ - 通过引用传递给模板函数

c++ - 指针作为成员或引用作为成员

c++ - cvNamedWindow 总是段错误

c++ - ANN 库中的前向声明

c++ - 模板中的预处理器条件

javascript - Polymer - 遍历模板中的对象

c++ - 从类的类型结构中获取值

c++ - 什么时候使用模板显式实例化?