“前向不可破坏”访问器类模板[C ++] [英] "Forward-unbreakable" accessor class templates [C++]

查看:260
本文介绍了“前向不可破坏”访问器类模板[C ++]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除非我完全错了,getter / setter模式是一个常用的模式,用于两件事:

Unless I am thoroughly mistaken, the getter/setter pattern is a common pattern used for two things:


  1. 因此只能通过提供一个 getVariable 方法(或者更少见,只能修改,只需提供一个 setVariable 方法)。

  2. 要确保,在将来,如果你碰巧有一个问题,一个好的解决方案将简单地处理该变量它进入和/或离开类,您可以通过使用getter和setter方法上的实际实现来处理该变量,而不是简单地返回或设置值。这样,更改不会传播到其余代码。

  1. To make a private variable so that it can be used, but never modified, by only providing a getVariable method (or, more rarely, only modifiable, by only providing a setVariable method).
  2. To make sure that, in the future, if you happen to have a problem to which a good solution would be simply to treat the variable before it goes in and/or out of the class, you can treat the variable by using an actual implementation on the getter and setter methods instead of simply returning or setting the values. That way, the change doesn't propagate to the rest of the code.

问题1:我缺少任何使用访问器或者我的任何假设不正确?我不知道这些是否正确。

Question #1: Am I missing any use of accessors or are any of my assumptions incorrect? I'm not sure if I am correct on those.

问题2:有什么样的模板好处,可以阻止我写我的访问器成员变量?我没有找到任何。

Question #2: Are there any sort of template goodness that can keep me from having to write the accessors for my member variables? I didn't find any.

问题3:下面的类模板是一个实现getter的好方法,而不必实际写入accesor?

Question #3: Would the following class template be a good way of implementing a getter without having to actually write the accesor?

template <class T>
struct TemplateParameterIndirection // This hack works for MinGW's GCC 4.4.1, dunno others
{
    typedef T Type;
};

template <typename T,class Owner>
class Getter
{
public:
    friend class TemplateParameterIndirection<Owner>::Type; // Befriends template parameter

    template <typename ... Args>
    Getter(Args args) : value(args ...) {} // Uses C++0x

    T get() { return value; }

protected:
    T value;
};

class Window
{
public:
    Getter<uint32_t,Window> width;
    Getter<uint32_t,Window> height;

    void resize(uint32_t width,uint32_t height)
    {
        // do actual window resizing logic

        width.value = width; // access permitted: Getter befriends Window
        height.value = height; // same here
    }
};

void someExternalFunction()
{
    Window win;

    win.resize(640,480); // Ok: public method

    // This works: Getter::get() is public
    std::cout << "Current window size: " << win.width.get() << 'x' << win.height.get() << ".\n";

    // This doesn't work: Getter::value is private
    win.width.value = 640;
    win.height.value = 480;
}

对我来说公平,我甚至可以重新实现 get 逻辑通过使用一些其他的部分模板专业化技巧。这同样适用于某些类型的Setter或者甚至GetterSetter类模板。

It looks fair to me, and I could even reimplement the get logic by using some other partial template specialization trickery. The same can be applied to some sort of Setter or even GetterSetter class templates.

你的想法是什么?

推荐答案

虽然从实现的角度来看,解决方案是整洁的,但在架构上,它只有一半。 Getter / Setter模式的目的是给予clas控制它的数据和减少耦合(即知道 数据存储的其他类)。这个解决方案实现前者但不完全后者。

Whilst the solution is neat from implementation point of view, architectually, it's only halfway there. The point of the Getter/Setter pattern is to give the clas control over it's data and to decrease coupling (i.e. other class knowing how data is stored). This solution achieves the former but not quite the latter.

事实上,其他类现在必须知道两个东西 - 变量的名称和getter上的方法(即 .get() ),而不是一个 - eg getWidth()。这导致耦合增加。

In fact the other class now has to know two things - the name of the variable and the method on the getter (i.e. .get()) instead of one - e.g. getWidth(). This causes increased coupling.

说完这一切,这是分裂的谚语的头发。

Having said all that, this is splitting proverbial architectural hairs. It doesn't matter all that much at the end of the day.

编辑确定,现在是为了its its和嘻哈,这里是一个版本的getter使用运算符,所以你不必做 .value .get()

EDIT OK, now for shits and giggles, here is a version of the getter using operators, so you don't have to do .value or .get()

template <class T>
struct TemplateParameterIndirection // This hack works for MinGW's GCC 4.4.1, dunno others
{
    typedef T Type;
};

template <typename T,class Owner>
class Getter
{
public:
    friend TemplateParameterIndirection<Owner>::Type; // Befriends template parameter

    operator T()
    {
        return value;
    }

protected:
    T value;

    T& operator=( T other )
    {
       value = other;
       return value;  
    }


};

class Window
{
public:
    Getter<int,Window> _width;
    Getter<int,Window> _height;

    void resize(int width,int height)
    {
        // do actual window resizing logic
        _width = width; //using the operator
        _height = height; //using the operator
    }
};

void someExternalFunction()
{
    Window win;

    win.resize(640,480); // Ok: public method
    int w2 = win._width; //using the operator
    //win._height = 480; //KABOOM
}

EDIT 固定硬编码分配运算符。如果类型本身具有赋值运算符,这应该工作得相当好。默认情况下,结构体有简单的结构,它应该是开箱即用的。

EDIT Fixed hardcoded assignment operator. This should work reasonably well if the type itself has an assignment operator. By default structs have those so for simple ones it should work out of the box.

对于更复杂的类,你需要实现一个足够公平的赋值运算符。使用 RVO Copy On Write 优化,这在运行时应该是相当有效的。

For more complex classes you will need to implement an assignment operator which is fair enough. With RVO and Copy On Write optimizations, this should be reasonably efficient at run time.

这篇关于“前向不可破坏”访问器类模板[C ++]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆