【问题标题】:How to hide a field via define and provide only setter and getter?如何通过定义隐藏字段并仅提供setter和getter?
【发布时间】:2012-08-11 21:15:42
【问题描述】:

我想知道如何隐藏一个真实的属性字段(不是将其设为私有或公共,而是强制使用 setter 和 getter)并为他提供简单的 setter 和 getter。所以我想知道如何创建这样的api:

private:
    Property( int my_a);
public:
    Property( int my_b);
...
{
 set_my_a(1);
 cout << get_my_a() << endl;
 // my_a = 13; // will cause compiler error
...

如何通过 Boost 预处理器创建这样的东西?

【问题讨论】:

  • 这和boost有关吗?一般的方法是将变量设为私有
  • 你为什么要这么做?如果 getter 和 setter 没有自定义,属性就没有意义。
  • @DeadMG:确实 - 我想自定义 Geters 和 Setter,但我想知道用 geter 和 setter 函数包装字段的一般方法。

标签: c++ boost boost-preprocessor


【解决方案1】:

你真的需要使用 boost 预处理器吗? 您在下面有一个没有提升的解决方案:

// property.h    
#include <stdio.h>

#define property(type) struct : public Property <type>  

template <typename T>
class Property 
{
protected:
  T value;
public:
  virtual T get() { 
    return value; 
  }
  virtual void set(T new_value) { 
    value = new_value; 
  }
};

用法示例:

// test.cpp
#include "property.h"

class Test {
public:
  property(int) {} a;

  property(int)  {
    int get() { 
      return value * 10; 
    } 
  } b;

  property(int) {
    void set(int x) {
      value = x * 200;
    } 
  } c;

  property(int) {
    int get() { 
      return value * 3000; 
    } 
    void set(int x) {
      value = x * 443;
    } 
  } d;
};

main()
{
  Test t;

  printf("i\ta\tb\tc\td\t\n");
  for (int i=0; i<10; i++) { 
    t.a.set(i);
    t.b.set(i);
    t.c.set(i);
    t.d.set(i);
    printf("%i\t%i\t%i\t%i\t%i\n", i, t.a.get(), t.b.get(), t.c.get(), t.d.get());
  }
}

http://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B 中的 wikipedia 解决方案很好,但需要进行少量修改才能变得有用,因为没有受保护的语句,您无法编写自己的 getter 和 setter。

#include <iostream>

template <typename T> 
class property {
protected:
  T value;
public:
  T & operator = (const T &i) {
    ::std::cout << i << ::std::endl;
    return value = i;
  }
  operator T const & () const {
    return value;
  }
};

struct Bar {
  property <bool> alpha;
  struct :public property <int> {
    int & operator = (const int &i) {
      ::std::cout << "new setter " << i << ::std::endl;
      return value = i;
    }
  } bravo;
};

main() 
{
  Bar b;
  b.alpha = false;
  b.bravo = (unsigned int) 1;
}

如果你愿意,你可以再改变一点:

#include <iostream>
#define SETTER(type) public: type& operator=(const type new_value)
#define GETTER(type) public: operator type const & () const

template <typename T> 
class Property {
protected:
  T value;
public:
  T & operator = (const T &i) {
    ::std::cout << i << ::std::endl;
    return value = i;
  }
  template <typename T2> T2 & operator = (const T2 &i) {
    ::std::cout << "T2: " << i << ::std::endl;
    T2 &guard = value;
    throw guard; // Never reached.
  }
  operator T const & () const {
    return value;
  }
};

struct Bar {
  Property <bool> alpha;
  struct:Property <int> {
    SETTER(int) {
      value = new_value * 1000;
      ::std::cout << "new method " << new_value << ::std::endl;
      return value;
    }
    GETTER(int) {
      return value/1000;
    }
  } bravo;
};

main() 
{
  Bar b;
  b.alpha = false;
  b.bravo = (unsigned int) 1;
  ::std::cout << b.bravo << ::std::endl;
}

【讨论】:

    【解决方案2】:

    而不是重写一个实现的例子,这是维基百科上的一个链接:http://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B

    这基本上强制通过 getter/setter 方法访问属性。获得所需效果所需的升级是将函子传递给这些属性的能力。有很多关于实施这些的想法;我无法建议的最佳方法取决于您的发展需求。就个人而言,这感觉像是过度工程,并且更喜欢只使用 Pimpl 来隐藏我的私人细节并明确提供 getter/setter。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多