문제

지 않는 한 나는 철저하게 잘못이터 구 패턴은 일반적인 패턴은 두 가지를 사용:

  1. 비공개 변수는 사용할 수 있습니다,하지만 결코 수정에 의해서만 제공하는 getVariable 방법(또는지만 수정할 수 있으로만 제공 setVariable method).
  2. 는지 확인하는,미래에 일어날 경우에 문제가있는 좋은 해결책이 될 것이 단순히 치료하는 변수에 들어가기 전에 그리고/또는 클래스에,당신은 당신을 치료할 수 있는 변수를 사용하여 실제 구현에 getter 및 setter 방법 대신 자이나 설정값입니다.는 방법,변경이 적용되지 않 나머지 부분의 코드입니다.

질문#1:나는 모든 사용의 접근 또는 내 가정을 반드시 보장되지는 않습니다나는 확실하지 않다면 내가 올바른 이들에.

질문#2:는 거의 모든 종류의 템플릿을 선을 유지할 수 있는 나에게서를 작성 접근을 위한 내 구성원 변수가?나를 찾을 수 없습니다.

질문#3:것 다음과 같은 템플릿 클래스의 좋은 방법이 될 구현 getter 하지 않고도 실제로 쓰기 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 논리를 사용하여 다른 부분 템플릿을 전문화는 속임수.동일 적용할 수 있는 일종의 세터 또는 GetterSetter 템플릿 클래스.

당신의 생각은 무엇입니까?

도움이 되었습니까?

해결책

는 이 솔루션은 깔끔한에서 구현,관점 architectually,그만 중간에 있다.의 포인트 get/set 패턴을 제공하는 것입 clas 컨트롤을 통해 그것의 데이터 및 감소 커플링(i.e다른 클래스 알 는 방법 데이터가 저장된다).이 솔루션을 달성한 전지만 아주 후자입니다.

사실 다른 클래스에 이은 두 가지를 알아-의 변수 이름을과 방법에 게터(i.e .get() 어)에서 대신의 하나-예를 들어, getWidth().이로 인해 증가 연결할 수도 있습니다.

모든 말했다,이것은 분명한 건축 머리카락이다.그것이 문제가되지 않는 모두에서 많이 하루의 끝.

편집 확인,지금은 배설물과 웃음기 버전의 게터를 사용하여 연산자는,그래서 당신이 할 필요가 없 .value.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
}

편집 고정 하드 할당 연산자입니다.이 일을 해야 합리적으로 잘 유형의 경우에는 그 자체가 지정 연산자입니다.기본적으로 구조체가 사람들을 위한 간단한 사람이 그것을 밖으로 작동 합니다.

더 복잡한 클래스를 구현해야 할당 운영자는 공정한 충분합니다.가 RVO사본에 쓰기 최적화 이해야 합리적으로 효율적입니다.

다른 팁

FWIW 여기에는 나의 의견이 당신의 질문:

  1. 일반적으로 이 지점이 있는 비즈니스 로직 또는 다른 제약 조건에서 적용하였습니다.할 수도 있습 계산 또는 가상의 변수를 디커플링 인스턴스의 변수에 접근 방법이 있습니다.
  2. 하지 않는 것으로 알고 있다.프로젝트가 일에 있었다의 가족 C 매크로 스탬프 이러한 방법
  3. Yes;내가 생각하는 매우 깔끔합니다.나는 그냥 그것을 고민하지 않는 문제 가치,그것은 혼동하는 다른 개발자(하나의 개념이 더 필요에 맞게 자신의 머리)지 절약 훨씬 넘는 각인 등의 방법을 수 있습니다.

이후 Igor Zevaka 게시는 하나의 버전이 나는 게시물 중 하나 나는 오랜 시간 전입니다.이것은 약간 다르-나에서 관찰하는 시간 의 실제 사용 get/set 쌍(는 실제로는 아무것도 않았다)었을 적용하는 변수 값을 내에서 머무는 사전에 결정된 범위입니다.이것은 좀 더 광범위한과 같은 추가 I/O 사업자가 추출기는 여전히 적용의 정의된 범위에 있습니다.그것은 또한 그것의 비트 테스트/코드를 표시의 일반적인 아이디어 그것이 무엇이며 어떻게 그것은 그것:

#include <exception>
#include <iostream>
#include <functional>

template <class T, class less=std::less<T> >
class bounded {
    const T lower_, upper_;
    T val_;

    bool check(T const &value) {
        return less()(value, lower_) || less()(upper_, value);
    }

    void assign(T const &value) {
        if (check(value))
            throw std::domain_error("Out of Range");
        val_ = value;
    }

public:
    bounded(T const &lower, T const &upper) 
        : lower_(lower), upper_(upper) {}

    bounded(bounded const &init) 
        : lower_(init.lower), upper_(init.upper)
    { 
        assign(init); 
    }

    bounded &operator=(T const &v) { assign(v);  return *this; }

    operator T() const { return val_; }

    friend std::istream &operator>>(std::istream &is, bounded &b) {
        T temp;
        is >> temp;

        if (b.check(temp))
            is.setstate(std::ios::failbit);
        else
            b.val_ = temp;
        return is;
    }
};


#ifdef TEST

#include <iostream>
#include <sstream>

int main() {
    bounded<int> x(0, 512);

    try {
        x = 21;
        std::cout << x << std::endl;

        x = 1024;
        std::cout << x << std::endl;
    }

    catch(std::domain_error &e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    std::stringstream input("1 2048");
    while (input>>x)
        std::cout << x << std::endl; 

    return 0;
}

#endif
  1. 사용할 수도 있습니다 getter 또는 세터 입력되는 것을 방지 또는 집합 계산 가능한 값은,많은 방법이 속성에서 사용되는 다른 언어는 C#

  2. 나는 생각할 수 없는 합리적인 방법을 추상화하고 설정의의 값/속성입니다.

  3. 나는 익숙하지 않은 충분한 C++소 표준다.

이 과 이 경우에는지 확인해야 합니다 변호사/클라이언트의 관용구에 대한 현명한 우정을 사용한다.을 찾기 전에 이의 관용구,내가 피할 우정합니다.

http://www.ddj.com/cpp/184402053/

그리고 지금 질문,그리고 무엇이 필요한 경우 setter 뿐만 아니라.

내가 당신에 대해 알고하지 않지만,나는 경향이 있(대략)두 가지 형태의 클래스:

  • 클래스에 대한 로직
  • blobs

양은 느슨한 컬렉션의 모든 속성의 비즈니스 개체입니다.예를 들어, Personsurname, firstname, 여러 주소,여러 가지 직업...그래서 Person 지 않을 수도 있는 논리입니다.

를 도울 수 있습니다.,내가 사용하는 경향이 정식 개인 특성에+getter+setter 때문에,그것은 초록의 실제 구현에서 클라이언트입니다.

그러나,하지만 이 템플릿(그리고 그것의 진화에 의해 이고르 Zeveka)은 정말 좋은,그들은하지 않는 주소를 설정에 문제가지 주소 바이너리 호환성 문제입니다.

난 것이 아마 리조트 매크로...

다음과 같습니다.

// Interface
// Not how DEFINE does not repeat the type ;)
#define DECLARE_VALUE(Object, Type, Name, Seq) **Black Magic Here**
#define DEFINE_VALUE(Object, Name, Seq) ** Black Magic Here**

// Obvious macros
#define DECLARE_VALUER_GETTER(Type, Name, Seq)\
   public: boost::call_traits<Type>::const_reference Name() const

#define DEFINE_VALUE_GETTER(Object, Name)\
   boost::call_traits<Name##_type>::const_reference Object::Name ()const\
   { return m_##Name; }

#define DECLARE_VALUE_SETTER(Object, Type, Name)\
   public: Type& Name();\
   public: Object& Name(boost::call_traits<Type>::param_type i);

#define DEFINE_VALUE_SETTER(Object, Name)\
   Name##_type& Object::Name() { return m_##Name; }\
   Object& Object::Name(boost::call_traits<Name##_type>::param_type i)\
   { m_##Name = i; return *this; }

는 것처럼 사용:

// window.h
DECLARE_VALUE(Window, int, width, (GETTER)(SETTER));

// window.cpp
DEFINE_VALUE(Window, width, (GETTER)); // setter needs a bit of logic

Window& Window::width(int i) // Always seems a waste not to return anything!
{ 
  if (i < 0) throw std::logic_error();
  m_width = i;
  return *this;
} // Window::width

의 비트와 함께 전처리기 매직 그것은 확실히 잘 작동합니다!

#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/rem.hpp>

#define DECLARE_VALUE_ITER(r, data, elem)\
  DECLARE_VALUE_##elem ( BOOST_PP_TUPLE_REM(3)(data) )

#define DEFINE_VALUE_ITER(r, data, elem)\
  DEFINE_VALUE_##elem ( BOOST_PP_TUPLE_REM(2)(data) )

#define DECLARE_VALUE(Object, Type, Name, Seq)\
   public: typedef Type Name##_type;\
   private: Type m_##Name;\
   BOOST_PP_SEQ_FOREACH(DECLARE_VALUE_ITER, (Object, Type, Name), Seq)

#define DEFINE_VALUE(Object, Name, Seq)\
   BOOST_PP_SEQ_FOREACH(DEFINE_VALUE_ITER, (Object, Name), Seq)

좋아,형식이 안전하지 않으며 모든지만,:

  • 그것은 합리적인 설정의 매크로 생각
  • 그것은 사용하기 쉽고,사용자만이 이제까지에 대해 걱정하 2 매크로 모든 후,그 다음과 같 템플 오류를 얻을 수 있는 털이
  • 사용 합니다.call_traits 효율성에 대한(const&/값 선택)
  • 거기에 더 많은 기능이 있다:get/set duo

  • 그것은 불행하게도,정으로...고 불평하지 않습니다면 당신이 이제까지

  • 이란 접근자(public,protected,private)도록하는 것은 좋지 않습니다 intersped 전체 클래스

여기에 정규를 들어 다음:

class Window
{
  // Best get done with it
  DECLARE_VALUE(Window, int, width, (GETTER));
  DECLARE_VALUE(Window, int, height, (GETTER));

// don't know which is the current access level, so better define it
public:

};

당신이 해결이 잘못된 문제입니다.에서는 잘 설계된 응용 프로그램,현야 희귀,자동화되지 않습니다.는 의미있는 클래스가 제공하는 몇 가지 종류의 추출.그것은 단순히 컬렉션 멤버 모델하는 개념이상의 구성원 변수입니다.그리고 일반적으로도 의미를 노출하는 개별적인 회원입니다.

클래스에 노출시키는 작업을 의미 개념에서는 모델입니다.대부분의 회원은 변수가 있을지 이상 상태를 저장하는 당신이 필요합니다.하지만 그것은 일반적으로 수 없 직접 액세스. 그 이유는 그것은 개인의 구성원 등에서 첫 번째 장소.

보다는 쉽게 찾을 방법을 쓰기 car.getFrontLeftWheel(), 자신에게 물어 이유로 클래스 사용자가 필요한 전면 왼쪽 휠에서 첫 번째 장소입니다.당신은 일반적으로 조작하는 휠을 직접 운전하는 경우?차를 돌의 모든 바퀴 회전하는 비즈니스에 대한 당신,그렇지 않나요?

이것은 생각 #defines 은 여전히 유용합니다.

템플릿은 버전은 복잡하고 이해하기 어렵-정 버전은 분명

#define Getter(t, n)\
     t n;\
     t get_##n() { return n; }

class Window
{
    Getter(int, height);
}

내가 있는 구문에 약간의 잘못을-하지만 당신은 점을 얻는다.

는 경우가 있었는 잘 알려진의 설정 템플릿에서,말씀,부스트 그때 나는 그들을 사용합니다.하지만 내가 쓸 것 나 자신입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top