2014-11-11 2 views
3

를 얻을, 우리는이 클래스가 있습니다. 내가 그런 일을 호출 할 수 있습니다 어디 적은 방법 set()get()을 만들에 관심이 :좋은 세트를 만드는 방법/방법 예를 들어

int main() 
{ 
    Coord c; 

    c.set.x(5); /* only set x */ 
    c.set.y(6); /* or y */ 
    c.set.z(7); /* or z */ 
    c.set(1,2,5); /* or setting x, y and z */ 

    c.get.x(); /* only get x */ 
    c.get.y(); /* or y */ 
    c.get.z(); /* or z */ 
} 
+3

그렇게하지 마십시오! –

+0

@KarolyHorvath 왜? 내 실제 수업이 더 좋다고 생각하니? – marquesm91

+1

@KarolyHorvath 그 일을하지 않는 이유를 알려주십시오. – sfrehse

답변

6

, 그것은 또한 struct 수 있습니다. 유효성 검사가 중요하지 않은 경우입니다,

Coord c; 

c.set<Coord::x>(5); /* only set x */ 
c.set<Coord::y>(6); /* or y */ 
c.set<Coord::z>(7); /* or z */ 
c.set(1,2,5); /* or setting x, y and z */ 

c.get<Coord::x>(); /* only get x */ 
c.get<Coord::y>(); /* or y */ 
c.get<Coord::z>(); /* or z */ 
+0

그게 내가 찾고있는거야! 고맙다 @ 마리오! – marquesm91

+0

setter 함수의 매개 변수를 const 참조로 전달하는 것이 좋습니다. 그래서 ** void set (double v) ** 대신 void ** (const double & v) **를 사용할 수 있습니다. 이 경우별로 중요하지 않지만 클래스 객체를 전달하는 경우 임시 객체를 만들지 않아도됩니다. –

+0

@VishalGupta 좋은 관찰! 나는 고마워! – marquesm91

0

첫째 : 당신이 당신의 객체 c에 공개 요소 set를 호출하고 set이이 곳 때문에 c.set.x 귀하의 사용이 작동하지 않을 것입니다 공개 요소 x.

두 클래스 모두 깨끗한 코드와 일반적인 스타일의 getter 및 setter가 부족하다는 것을 알았습니다. 어떤 언어도 지정하지 않아도 마찬가지입니다.

일반적인 방법으로는 다음과 같은 작성하는 것입니다 :

class Coord 
{ 
    double x; 
    double y; 
    double z; 

public: 

    Coord() { 
    x = 0; 
    y = 0; 
    z = 0; 
    } 

    Coord(double x, double y, double z) 
    { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
    } 

    void setX(double x) { this.x = x; } 
    void setY(double y) { this.y = y; } 
    void setZ(double z) { this.z = z; } 

    double getX() { return x; } 
    double getY() { return y; } 
    double getZ() { return z; } 
}; 

을 일부 세터 변수 매개 변수 또는 다른 규칙으로 m_x 사용하는 것을 선호하지만.

누구나 모든 사람이 코드를 직접 이해합니다. 설정 및 X, Y, Z에 대한 좌표 값을 얻을 수 있으며, 누군가가 다음 않으면 꽤 표준 기본-행동을 보일 것이다 : 당신은 정확하게 당신이 원하는 것을 할 수 없습니다

Coord P(10, 15, 20); 
std::cout << P.getX() << " " << P.getY() << std::endl; 
P.setX(-10); 
P.setZ(40); 
+0

포인터를 사용하여 더 많이 청소할 수 있습니다. 좋은 제안! Stefan에게 감사드립니다! – marquesm91

-1

. (set#define -d 매크로 아니라면 있지만 그 바보 같은 것)

c.set.x(5); /* only set x */ 

에서

c.set 표현식은 cset의 필드를 검색한다.

+0

'set '이 객체를 가리키는 참조 일 경우 어떻게해야할까요? :) –

+0

그러면'c.x (5)'코드는 더 간단합니다. –

0

이미 좋은 답변을 얻었으나 더 적은 세터와 게터로 구문을 실제로 원한다면 열거 형을 사용할 수도 있습니다. 클라이언트 문법은 다소 어색하고 어색하지만, 물론 당신이 찾고있는 것에 달려 있습니다! Coord 클래스는 간단 경우

#include <iostream> 

class Coord { 
public: 

    enum Axis { 
     X = 0, 
     Y, 
     Z, 
     NUM_AXES 
    }; 

    // Using extended initializer lists (C++11) 
    Coord() : axes_{0, 0, 0} {} 
    Coord(double x, double y, double z) : axes_{x, y, z} {} 

    void set(Axis a, double d) { 
     axes_[a] = d; 
    } 
    double get(Axis a) const { 
     return axes_[a]; 
    } 

private: 
    double axes_[NUM_AXES]; 

    // Copy constructor and assgn. operator included for good measure 
    Coord(const Coord &); 
    void operator=(const Coord &); 
}; 

int main() 
{ 
    Coord c(1, 2, 3); 
    std::cout << "X: " << c.get(Coord::X) << std::endl; 
    std::cout << "Y: " << c.get(Coord::Y) << std::endl; 
    std::cout << "Z: " << c.get(Coord::Z) << std::endl; 
    c.set(Coord::Y, 4); 
    std::cout << "Y: " << c.get(Coord::Y) << std::endl; 
    return 0; 
} 
0

이 노출하는 더 많거나 적은 표준 방법 :

어쨌든 당신과 같이 쓸 수 있습니다 :

class Coord 
{ 
public: 
    enum xyz {x = 0, y, z}; 

    Coord() : vec{x, y, z} {} 

    template<xyz C> void set(double v) { vec[C] = v; } 
    template<xyz C> double get() const { return vec[C]; } 

    void set(double xx, double yy, double zz) 
    { 
    set<Coord::x>(xx); 
    set<Coord::y>(yy); 
    set<Coord::z>(zz); 
    } 

private: 
    double vec[z + 1]; 
}; 

을하고 수업이 방법을 사용 non-const 접근기에서 변경 가능한 참조를 반환하고 const에서 값을 반환합니다. 이렇게하면 구문을 너무 무겁게 만들지 않고 인터페이스를 저장소에서 분리 할 수 ​​있습니다.

private: 
    double m_x, m_y, m_z; 

public: 
    double & x() { return m_x; } 
    double & y() { return m_y; } 
    double & z() { return m_z; } 

    double x() const { return m_x; } 
    double y() const { return m_y; } 
    double z() const { return m_z; } 

c.x()은의 값을 획득 할 수있는 X Coord 객체 CONST인지하고 c.x() = value 구문을 사용하여 값을 설정하는 허용 여부 좌표.완전성의 관심에서


, 당신은 다음과 같은 코드를 사용하여 정확히 원하는 구문을 얻을 수 있지만, 난 강력하게 반대 추천 할 것입니다. 그것은 많은 여분의 코드이고, 실질적인 이익을 제공하지 않으며, 흔치 않은 문법을 만들고 대부분의 프로그래머는 그것을 직관적으로 찾지 못할 것입니다.

이 기술은 두 개의 중첩 클래스 인 getterssetters을 생성하고 이들의 인스턴스를 Coord의 공용 멤버로 제공합니다.

이것은 요청한 결과를 얻는 방법의 예로서 제공되지만이 방법은 권장하지 않습니다.

class Coord 
{ 
private: 
    double x, y, z; 

public: 
    Coord(); 
    Coord(double, double, double); 

    class setters { 
     friend class Coord; 

    private: 
     explicit setters(Coord &); 

    public: 
     setters(setters const &) = delete; 
     setters & operator=(setters const &) = delete; 

     void x(double) const; 
     void y(double) const; 
     void z(double) const; 

    private: 
     Coord & coord; 
    }; 
    friend class setters; 

    class getters { 
     friend class Coord; 

    private: 
     explicit getters(Coord const &); 

    public: 
     getters(getters const &) = delete; 
     getters & operator=(getters const &) = delete; 

     double x() const; 
     double y() const; 
     double z() const; 

    private: 
     Coord const & coord; 
    }; 
    friend class getters; 

    setters const set; 
    getters const get; 
}; 

Coord::Coord() : x(0), y(0), z(0), set(*this), get(*this) { } 

Coord::Coord(double px, double py, double pz) : x(px), y(py), z(pz), set(*this), get(*this) { } 

Coord::setters::setters(Coord & c) : coord(c) { } 

void Coord::setters::x(double px) const { 
    coord.x = px; 
} 

void Coord::setters::y(double py) const { 
    coord.y = py; 
} 

void Coord::setters::z(double pz) const { 
    coord.z = pz; 
} 

Coord::getters::getters(Coord const & c) : coord(c) { } 

double Coord::getters::x() const { 
    return coord.x; 
} 

double Coord::getters::y() const { 
    return coord.y; 
} 

double Coord::getters::z() const { 
    return coord.z; 
} 

(Demo)

+0

을 참조하십시오. 'x','y'와'z' 공개? –

+0

@JohannesS .: 전화를 가로 챌 수 있습니다. –

+1

@ JohannesS. 실제 데이터 표현은 클래스 사용자에게 노출되지 않습니다. 예를 들어 public-facing 이름을 유지하면서 배열에 저장할 수 있습니다. – cdhowie

1

getter 및 setter는 데이터를 보호하고 캡슐화를 제공하기위한 것입니다.

예를 들어 로그에 쓰기와 같은 작업을 가져오고 설정하는 데 부작용을 추가하거나 나중에 끔찍한 문제가 발생하기 전에 유효하지 않은 값을 잡을 수 있습니다 (예 : n이 세트).

void set_x(int x) 
{ 
    // prevent an invalid value for x 
    if(x > 11) x = 11; 

    // set x 
    this.x = x; 

    // log the operation 
    log("user set x to {0}", x);  
} 

일부 괴팍스러운 처리기 매크로를 사용하지 않는 당신의 c.set.x(5) 예를 가정하면, 그것은 좌표 운전 클래스는 방법

x() 
y() 
z() 
set라는 멤버 변수를 가지고 필요 :

여기에 간단한과 인위적인 세터 예제

Coord 클래스에 set_x(), set_y()set_z() 메서드를 작성하는 것만 큼 많은 코드가 필요합니다. 그러나 메서드는 Coord 클래스에 속하지 않고 대신 Coord의 멤버 변수로 사용되는 다른 클래스에 속합니다. 그렇게하는 것은 실제로 논리적 인 의미를 갖지 않을 것입니다 ... x, y 및 z 값은 Coord에 속하며 그것들에 대한 연산은 Coord에 대한 연산입니다.

또한 x()y()z()의 메소드는 더 이상 메소드 동사를 만드는 일반적인 원칙을 따르지 않습니다. 이 메소드를 사용하여 클래스를 읽는 사람은 z() 함수가 어떤 역할을하는지 알지 못합니다!

또한 리펙토링 악몽을 만듭니다. 예를 들어 미래에 비즈니스 요구 사항이 나타나면 Coords가 x의 값을 21 이상으로 유지할 수 없다는 것을 의미합니다. 코드를 유지하면 코드의 구성원 인 클래스를 변경해야합니다. Coord 클래스 자체가 아닌 Coord입니다.

getter 및 setter 메서드로 캡슐화하는 것이 종종 좋은 생각이며 C++에서는 인라인을 사용하여 런타임 오버 헤드를 추가 할 수도 있습니다. 그러나 모든 것을 "가능한 한 간단하게", "단순하게하지 말라"는 원칙을 지키십시오. 즉, get_x() 및 set_x()는 널리 이해되고 유용하며 쉽게 리팩토링되고 편리하며 자체 문서화되고 효율적입니다. 다른 접근 방식은 그럴 가능성이 적습니다.

0

이 이상한 코드는 정확히 당신이 묻는 것입니다. 단지 C++ 재미입니다. 이러지 마!

#include <iostream> 
using namespace std; 

class Coord { 
    double x; 
    double y; 
    double z; 

public: 
    class Setter { 
    public: 
     Setter(Coord& coord) : c(coord) {} 
     void x(double value) { c.x = value; } 
     void y(double value) { c.y = value; } 
     void z(double value) { c.z = value; } 
     void operator()(double x, double y, double z) { c.x = x; c.y = y; c.z = z; } 
    private: 
     Coord& c; 
    }; 

    class Getter { 
    public: 
     Getter(Coord& coord) : c(coord) {} 
     double x() { return c.x; } 
     double y() { return c.y; } 
     double z() { return c.z; } 

    private: 
     Coord& c; 
    }; 

    Setter set; 
    Getter get; 

    Coord() : set(*this), get(*this) { x = y = z = 0; } 

    friend class Setter; 
}; 

int main() 
{ 
    Coord c; 

    cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl; 

    c.set.x(1); 
    c.set.y(2); 
    c.set.z(3); 

    cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl; 

    c.set(5, 6, 7); 

    cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl; 

    return 0; 
} 

출력 : 다음과 같이 실제로 기능이 귀하의 요구 사항에 따라 줄일 수 있습니다

0 0 0 
1 2 3 
5 6 7 
+0

'set'과'get'은'const'로 선언되어야합니다. 그렇지 않으면'Coord a, b; a.get = b.get;'등 – cdhowie

+0

이 코드에 대한 내 의견은 '하지 마라!'나는 OP 구문을 가능케하는 100 % 정확하고 완벽한 코드로 만들려고 노력하지도 않습니다. –

0

,

class Coord 
{ 
    double x; 
    double y; 
    double z; 

    public: 

     Coord() { 
      x = 0; 
      y = 0; 
      z = 0; 
     } 

     void GetValues(double* x=NULL, double* y=NULL, double* z=NULL); 
     void SetValues(double x=0, double y=0, double z=0) 

     /* You can use constructors like below to set value at the creation of object*/ 
     Coord(double x, double y, double z) 
     { 
     this.x = x; 
     this.y = y; 
     this.z = z; 
     } 

    /*You can set the values of x, y & z in a single function as follows. It can be used at any time without restriction */ 
     void SetValues(double x, double y, double z) 
     { 
     if(x > 0) //It is optional to use condition so that you can update any one variable aloen by sending other two as ZERO 
     { 
      this.x = x; 
     } 
     if(y > 0) 
     { 
      this.y = y; 
     } 
     if(z > 0) 
     { 
      this.z = z; 
     } 
     } 

     /*You can Get the values of x, y & z in a single function as follows. Pass By Reference id the concept you need */ 
     void GetValues(double* x, double* y, double* z) 
     { 
     if(x != NULL) //It x is not null. 
     { 
      x = this.x; 
     } 
     if(y != NULL) 
     { 
      y = this.y; 
     } 
     if(z != NULL) 
     { 
      z= this.z; 
     } 
     } 

};

다음과 같이 호출 할 수 호출하는 동안,

SetValues(10, 20, 0); //To set x and y values alone. 
double x1 = 0;double y1 = 0;double z1 = 0; 
GetValues(&x1, &y1, &z1)//It will return the values x1 y1 and z1 as 10, 20 & 0