setter 和 getter 的模板

Posted

技术标签:

【中文标题】setter 和 getter 的模板【英文标题】:Templates for setters and getters 【发布时间】:2010-11-16 14:23:31 【问题描述】:

我不熟悉模板,但我想知道是否可以将它们用于 setter 和 getter 方法。例如在这种情况下:

double exmlClass::getA(void) const

    return a_;




void exmlClass::setA(const double& a)

    a_ = a;




double exmlClass::getB(void) const

    return b_;

如您所见,方法几乎相同,只是它们引用了另一个私有变量(a_、b_、c_)。有没有更优雅的方法来编写这些函数,或者在这种情况下像上面那样做是常见的做法?如果使用模板很常见,我会很感激您在上面的代码中如何使用它们。

我要问的另一个问题是如何正确声明 getter 和 setter。编码风格好吗?

double getA(void) const;
void setA(const double& a);

double getB(void) const;
void setB(const double& b);

double getC(void) const;
void setC(const double& c);

我的意思是 getter 应该始终是 const 并且 setter 将作为对对象的参数引用,而不是复制它,这可能会慢一点?

【问题讨论】:

如果你的班级有大量的 getter 和 setter,这是一个问题,我会认真 question its design。 我在一定程度上同意@sbi。正如那篇文章所暗示的那样,如果您使用 setter 和 getter 的唯一目的是访问私有的东西,那么这很愚蠢。但是,有一种情况本文没有涉及:当您有正当需要将私有数据视为半透明或完全不透明(字节序、序列化/反序列化等等)时,尤其是在类型为表示包装了多条数据。例如:codereview.stackexchange.com/questions/7786/… 另外,由于那篇文章的作者没有把它拼出来(只是在接近结尾处简单提到),我想从文章中强调一点:3. A lack of essential operators and other methods forces user programs to manipulate the object through the get and set accessor functions.如果你的访问者是运营商,这至少意味着该文章的作者不会[必然]有同样的抱怨。 @Brian:好吧,OP 有一些愚蠢的吸气剂并问 这是一种好的编码风格吗? 对于一个偏离 真理之路的新手来说,这是一个非常可靠的信号(™),而不是有人询问抽象出 getter 背后的一些实现细节。 【参考方案1】:

向反对者致敬!

Boost.Fusion.Map 是您正在寻找的基础。

namespace result_of = boost::fusion::result_of;

class MyClass

public:
  struct AType ;
  struct BType ;
  struct CType ;

  template <typename Type>
  typename result_of::at< DataType, Type >::type &
  access(Type)  return boost::fusion::at<Type>(mData); 

  template <typename Type>
  typename result_of::at< DataType, Type >::type const &
  get(Type) const  return boost::fusion::at<Type>(mData); 

  template <typename Type>
  void set(Type, typename result_of::at< DataType, Type >::type const & v)
  
    boost::fusion::at<Type>(mData) = v;
  

private:
  typedef boost::fusion::map <
    std::pair<AType, int>,
    std::pair<BType, std::string>,
    std::pair<CType, float> > DataType;
  DataType mData;
;

【讨论】:

那么,专门化其中一种方法来做不同的事情有多容易? (因为如果你不打算这样做,你还不如只拥有公共数据成员。) @Brian Vandenberg:很抱歉您的编辑被拒绝了;我调整了代码。【参考方案2】:

以某种方式设计您的程序,减少对 getter 和 setter 的需求。 您可以通过宏创建它们或实现某种属性语法(这是可能的,但总有一些东西不能正常工作).. 但是,我想只在需要时编写访问器或使用您的 IDE 生成它们是最好和最常用的方法。

至于您的第二个问题,您至少应该将它用于对象类型,对于原语,您并不真正需要它。就我个人而言,如果我无论如何都需要对象的副本,我也不使用它,但是其他人可能会声称最好明确地执行此操作。

【讨论】:

“以某种方式设计程序,减少对 getter 和 setter 的需求” 这违反了面向对象编程的封装规则... @peoro:我没有说他应该用公共成员替换访问者。他应该通过使用更有意义的函数来简单地操作他的数据。如果有这么多访问器除了返回和设置内部变量之外什么都不做,那么很可能这些类的使用与 POD 结构非常相似,因此只是看似封装。 @peoro:你也可以看看 sbis 链接。 好的,我将您的原始帖子理解为“没有设置器和获取器”。什么是 sbis 链接? 我漏掉了一个撇号。 sbi 评论了发布此 link 的问题【参考方案3】:

除非您想将成员包装在模板化访问器类(如this)中,否则我看不到模板直接帮助您压缩 getter/setter 对的方法。另一种可能性是使用 #define 宏来模拟 C# 属性(如果宏不会吓到您或任何阅读您的代码的人)。

您的 getter 是返回 (const) 对成员的引用、返回指向成员的指针还是复制它们取决于几个因素。您必须考虑复制它们是否成本高(性能方面),复制它们在语义上是否有意义,以及您返回的信息是否应该有可能比您的课程寿命更长'重新获取它(如果你返回一个成员的指针/引用,一旦你删除你的对象,它就会悬空)。如果你想允许成员为空的可能性,我会在引用上使用指针。

对于 getter,我倾向于返回除原语之外的任何东西的 const 引用,我复制了这些引用。对于 setter,通常有一个 const 引用参数。

【讨论】:

更简单的包装器:Boost.Fusion.Map.【参考方案4】:

技术上可以创建一个exmlClass::set&lt;PMF&gt; 函数模板以使exmlClass::set&lt;&amp;exmlClass::a_&gt; 有效。然而,这有什么意义呢?

【讨论】:

【参考方案5】:

不,您不能定义任何类型的模板来创建函数或类似函数的东西,其名称不受限制,例如 getAgetB、...。

宏可以做到,但这是一个更糟糕的主意。

我通常通过 const 引用传递/返回类对象,但像 double 这样的简单内置类型只是通过值:

public:
  const ClassType& getObj() const;
  void setObj(const ClassType& obj);
  double getNum() const;
  void setNum(double num);

【讨论】:

【参考方案6】:

理论上,你可以:

template<typename A, typename B, typename C>
class Object

private:
    A _a;
    B _b;
    C _c;

public:
    Object()
    
    ;  // eo ctor

    // properties

    A getA() const return(_a);
    void setA(const A& _val) _a = _val;

    // etc for B & C
; // eo class Object

    // .....

    Object<int, double, char> myObject;

我看到了几个问题。首先,getter/setter 不应该是“抽象”的,它们传达给你班级的用户。你打算怎么称呼这个getter/setter?得到() ?获取值()?这到底是什么意思?

其次,这定义了 3。您的对象需要多少个? 1、2、4、9?

第三,Getter/setter 的名称应与其功能相称:

getName()
getAddress()
getMovie()

听起来您只是想节省打字时间,而不是让您的设计复杂化的借口恕我直言。

关于您的第 2 点,返回对对象的引用(最好是 const),但不要打扰小的、完整的 POD(普通旧数据)类型,例如 int、char、bool 等。

【讨论】:

以上是关于setter 和 getter 的模板的主要内容,如果未能解决你的问题,请参考以下文章

getter和setter方法

IDEA设置生成带注释的getter和setter解决方案 (图文教程)

为什么使用Getter和Setter?Getter和Setter有什么区别?

Python中的setter和getter

Dart中类的getter和setter

GroovyGroovy 方法调用 ( Java 类成员及 setter 和 getter 方法设置 | Groovy 类自动生成成员的 getter 和 setter 方法 )