C ++ 11에는 C # 스타일 속성이 있습니까? 멋진 구문 설탕이

C #에는 getter 및 setter가있는 필드에 대한 멋진 구문 설탕이 있습니다. 또한 자동 구현 속성이 마음에 듭니다.

public Foo foo { get; private set; }

C ++에서 나는 작성해야

private:
    Foo foo;
public:
    Foo getFoo() { return foo; }

C ++ 11에 이러한 개념이있어 이에 대한 구문 설탕을 가질 수 있습니까?



답변

C ++에서는 자신 만의 기능을 작성할 수 있습니다. 다음은 명명되지 않은 클래스를 사용하는 속성 구현의 예입니다. Wikipedia 기사

struct Foo
{
    class {
        int value;
        public:
            int & operator = (const int &i) { return value = i; }
            operator int () const { return value; }
    } alpha;

    class {
        float value;
        public:
            float & operator = (const float &f) { return value = f; }
            operator float () const { return value; }
    } bravo;
};

자체 getter 및 setter를 제자리에 작성할 수 있으며 홀더 클래스 멤버 액세스를 원하는 경우이 예제 코드를 확장 할 수 있습니다.


답변

C ++에는이 기능이 내장되어 있지 않으므로 속성 기능을 모방 하는 템플릿정의 할 수 있습니다 .

template <typename T>
class Property {
public:
    virtual ~Property() {}  //C++11: use override and =default;
    virtual T& operator= (const T& f) { return value = f; }
    virtual const T& operator() () const { return value; }
    virtual explicit operator const T& () const { return value; }
    virtual T* operator->() { return &value; }
protected:
    T value;
};

속성정의 하려면 :

Property<float> x;

사용자 정의 getter / setter 를 구현하려면 상속하십시오.

class : public Property<float> {
    virtual float & operator = (const float &f) { /*custom code*/ return value = f; }
    virtual operator float const & () const { /*custom code*/ return value; }
} y;

읽기 전용 속성 을 정의하려면 :

template <typename T>
class ReadOnlyProperty {
public:
    virtual ~ReadOnlyProperty() {}
    virtual operator T const & () const { return value; }
protected:
    T value;
};

그리고 수업에서 사용하려면Owner :

class Owner {
public:
    class : public ReadOnlyProperty<float> { friend class Owner; } x;
    Owner() { x.value = 8; }
};

더 간결하게 만들기 위해 매크로 에서 위의 일부를 정의 할 수 있습니다.


답변

모든 플랫폼과 컴파일러에서 작동하는 C ++ 언어에는 없습니다.

그러나 크로스 플랫폼 호환성을 깨고 특정 컴파일러에 커밋하려는 경우 이러한 구문을 사용할 수 있습니다. 예를 들어 Microsoft Visual C ++에서 다음을 수행 할 수 있습니다.

// declspec_property.cpp  
struct S {
   int i;
   void putprop(int j) {
      i = j;
   }

   int getprop() {
      return i;
   }

   __declspec(property(get = getprop, put = putprop)) int the_prop;
};

int main() {
   S s;
   s.the_prop = 5;
   return s.the_prop;
}


답변

당신은 전용 유형의 멤버를 가지고와 재정 의하여 어느 정도 getter 및 setter를 에뮬레이트 할 수 operator(type)operator=그것을 위해. 그것이 좋은 아이디어인지 여부는 또 다른 질문이며 +1Kerrek SB의 답변으로 내 의견을 표현할 것입니다. 🙂


답변

지난 시간 동안 내가 모은 속성 클래스를 살펴볼 수 있습니다 : /codereview/7786/c11-feedback-on-my-approach-to-c-like-class-properties

다음과 같이 동작하는 속성을 가질 수 있습니다.

CTestClass myClass = CTestClass();

myClass.AspectRatio = 1.4;
myClass.Left = 20;
myClass.Right = 80;
myClass.AspectRatio = myClass.AspectRatio * (myClass.Right - myClass.Left);


답변

C ++ 11을 사용하면 Property 클래스 템플릿을 정의하고 다음과 같이 사용할 수 있습니다.

class Test{
public:
  Property<int, Test> Number{this,&Test::setNumber,&Test::getNumber};

private:
  int itsNumber;

  void setNumber(int theNumber)
    { itsNumber = theNumber; }

  int getNumber() const
    { return itsNumber; }
};

그리고 여기에 Property 클래스 템플릿이 있습니다.

template<typename T, typename C>
class Property{
public:
  using SetterType = void (C::*)(T);
  using GetterType = T (C::*)() const;

  Property(C* theObject, SetterType theSetter, GetterType theGetter)
   :itsObject(theObject),
    itsSetter(theSetter),
    itsGetter(theGetter)
    { }

  operator T() const
    { return (itsObject->*itsGetter)(); }

  C& operator = (T theValue) {
    (itsObject->*itsSetter)(theValue);
    return *itsObject;
  }

private:
  C* const itsObject;
  SetterType const itsSetter;
  GetterType const itsGetter;
};


답변

다른 많은 사람들이 이미 말했듯이 언어에 내장 된 지원이 없습니다. 그러나 Microsoft C ++ 컴파일러를 대상으로하는 경우 문서화 된 속성에 대한 Microsoft 특정 확장을 활용할 수 있습니다. 여기 .

다음은 링크 된 페이지의 예입니다.

// declspec_property.cpp
struct S {
   int i;
   void putprop(int j) {
      i = j;
   }

   int getprop() {
      return i;
   }

   __declspec(property(get = getprop, put = putprop)) int the_prop;
};

int main() {
   S s;
   s.the_prop = 5;
   return s.the_prop;
}