setter 和 getter 的模板

发布于 2024-10-03 06:25:33 字数 694 浏览 0 评论 0原文

我不熟悉模板,但我想知道是否可以将它们用于 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);

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

I am not familiar with templates, but I wonder, if it is possible to use them for setter and getter methods. For example in this situation:

double exmlClass::getA(void) const
{
    return a_;
}



void exmlClass::setA(const double& a)
{
    a_ = a;
}



double exmlClass::getB(void) const
{
    return b_;
}

As you can see, methods are almost the same, except they refer to another private variables (a_, b_, c_). Is there a more elegant way to write those functions or it is common practice to do like above in such situations? And if its common to use templates, I would appreciate example how you would use them in code above.

Another question I would ask is how should getters and setters be properly declared. Is it good coding style?

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);

I mean should getters be always const and setters take as argument reference to an object, rather than copy it, which would be probably a little bit slower?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜扑 2024-10-10 06:25:33

哈啰,反对者!

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;
};

Haro to the naysayers!

Boost.Fusion.Map is what you're looking for as a basis.

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;
};
春风十里 2024-10-10 06:25:33

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

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

design your programs in a way, that there is less need for getters and setters.
You could create them by a macro or implement some kind of propertysyntax(which is possible but there are always things that don't work right)..
However, I suppose just writing the accessors when they are needed or generate them with your IDE is the best and most usual way.

As for your second question, you should use it at least for object type, you don't really need it for primitives. Personally I don't use it either if I need a copy of the object anyway, however others may claim that it might be better to do this explicit.

一笔一画续写前缘 2024-10-10 06:25:33

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

getter 是否返回对成员的(常量)引用、返回对成员的指针或复制它们取决于几个因素。您必须考虑复制它们是否昂贵(性能方面),复制它们在语义上是否有意义,以及您返回的信息是否有可能比您的类更长寿。从中获取它(如果您返回一个指向成员的指针/引用,那么一旦您删除对象,它就会悬空)。如果您想允许成员为空的可能性,我会使用指针而不是引用。

对于 getters,我倾向于返回除了我复制的原语之外的任何内容的 const 引用。对于 setter 来说,通常有一个 const 引用参数。

I can't see a way for templating to directly help you compactify your getter/setter pairs unless you want to wrap your members inside templated accessor classes like this. Another possibility is using a #define macro to emulate C# properties (if macros don't scare you or anyone reading your code).

Whether your getters return (const) references to members, return pointers to members, or copy them depends on a few factors. You have to consider whether it's expensive to copy them (performance wise), whether it semantically makes sense to copy them, and whether it should be possible for the information you're returning to outlive the class you're getting it from (if you return a pointer/reference to a member, it will be left dangling as soon as you delete your object). And I'd use pointers over references if you want to allow for the possibility of the member being null.

For getters, I tend to return const references for anything but primitives, which I copy. For setters, it's conventional to have a const reference parameter.

新雨望断虹 2024-10-10 06:25:33

从技术上讲,可以创建单个 exmlClass::set 函数模板,以使 exmlClass::set<&exmlClass::a_> 有效。然而,这有什么意义呢?

It's technically possible to create a single exmlClass::set<PMF> function template such that exmlClass::set<&exmlClass::a_> is valid. However, what would be the point?

━╋う一瞬間旳綻放 2024-10-10 06:25:33

不,您不能定义任何类型的模板来创建具有无限名称集(例如 getAgetB、...)的函数或类似函数的内容。

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

我通常通过 const 引用传递/返回类对象,但仅通过值传递/返回简单的内置类型,例如 double :

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

No, you cannot define any sort of template that can create functions or function-like things with an unbounded set of names like getA, getB, ....

A macro could do it, but that's an even worse idea.

I typically pass/return a class object by const reference, but simple built-in types like double just by value:

public:
  const ClassType& getObj() const;
  void setObj(const ClassType& obj);
  double getNum() const;
  void setNum(double num);
如若梦似彩虹 2024-10-10 06:25:33

理论上,您可以:

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?获取A()? getAValue()?这到底意味着什么?

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

第三,getters/setters应该根据他们的功能进行适当的命名:

getName()
getAddress()
getMovie()

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

关于第二点,返回对对象的引用(最好是 const),但不要为小型整数 POD(普通旧数据)类型(例如 int、char、bool 等)而烦恼。

In theory, you could:

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;

There are several problems I see with this. Firstly is that getters/setters shouldn't be "abstract" in what they convey to the users of your class. What are you going to call this getters/setters? getA() ? getAValue()? What does that even mean?

Secondly, this defines 3. How many do you need for your objects? 1, 2, 4, 9?

Thirdly, Getters/setters should be named appropriately to their function:

getName()
getAddress()
getMovie()

It sounds like you just want to save on typing, never an excuse to complicate your design imho.

With regards to your 2nd point, return reference to objects (const, preferably) but don't bother with small, integral POD (Plain-Old-Data) types such as int, char, bool etcteras.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文