Skip to content

Instantly share code, notes, and snippets.

@onmoving
Last active December 11, 2015 16:58
Show Gist options
  • Save onmoving/4631169 to your computer and use it in GitHub Desktop.
Save onmoving/4631169 to your computer and use it in GitHub Desktop.

#const 멤버 함수

클래스의 멤버 함수를 const로 지정하면 함수 내에서 멤버 변수를 변경하지 않는 것을 컴파일 단계에서 체크할 수 있다.

class Point
{
    int x;
    int y;
public:
    Point(int _x =0 , int _y = 0 ):x(_x),y(_y) { }
    void Print( ) const // const 함수
    {
    	cout << x <<',' << y << endl;
    }

    int getX() const // const 함수
    {
    	return x;
    }

    int getY() const // const 함수
    {
    	return y;
    }

    void setX(int _x)
    {
    	x = _x;
    }

    void setY(int _y)
    {
    	y = _y
    }
};

void main( )
{
    const Point p1(2,3)
    Point p2(5,5);

    p1.Print();
    p2.Print();

    p1.setX(10);	// compile error: p1은 const 객체임
    p1.setY(10);	// compile error: p1은 const 객체임
    p2.setX(10);	// OK
    p2.setY(10);	// OK

    cout << "p1: " << p1.getX() << ", " << p1.getY() << endl;
    cout << "p2: " << p2.getX() << ", " << p2.getY() << endl;
}

#연산자 오버로딩

##연산자 오버로딩의 방법 2 가지

연자자를 오버로딩하는 방법은 2가지로 첫째로 클래스의 멤버함수로 구현하는 방법과 둘째로 전역함수로 구현하는 방법이 있다.

Point p1(0,1), p2(2, 3);

if(p1 == p2) {
	...
}

위 코드에서 p1 == p2를 컴파일러에서 아래 두 가지로 해석할 수 있다.

  • p1.operator == (p2): 연산자가 멤버함수로 구현된 것으로 해석
  • operator == (p1, p2): 연사자가 전역함수로 구현된 것으로 해석

두 가지 방법 중 멤버함수로 구현이 가능하다면 멤버함수 방법을 사용하고, 멤버함수 방법이 불가능한 경우에는 전역함수 방법을 사용하도록 한다.

멤버함수로 해석이 불가능한 경우는 첫번째 피연산자인 p1이 Point 객체가 아닌 다른 타입인 경우이다. 이 경우에는 전역함수 구현으로 해석이 된다.

int x = 10

if(x == p2) {
	...
}

위 코드에서는 x가 Point 형식이 아니므로 operator == (x, p2)로 해석된다.

##++연산자

전위 ++, 후위 ++의 구분

Point p1(0, 1), p2(2, 3)

++p1;	// p1.operator++()로 해석
p2++; // p2.operator++(0)로 해석

후위 ++인 경우 더비 인자로 0을 전달하는 것을 기억하자.

코드 예제

class Point
{
    int x;
    int y;
public:
    Point(int _x =0 , int _y =0 ):x(_x),y(_y) { }
    void Print( )const { cout << x <<',' << y << endl; }
    const Point& operator++ ( ) // 전위 ++
    {
        x++;
        y++;
        return *this;
    }
    const Point operator++(int ) // 후위 ++
    {  
        Point pt(x, y);
        ++x;
        ++y;
        return pt;
    }
};

void main( )
{
    Point p1(2,3), p2(2,3);
    Point result;

    result = ++p1; // p1.operator++(); 와 같습니다.
    p1.Print();
    result.Print();

    result = p2++; // p2.operator++(0); 와 같습니다.   
    p2.Print();
    result.Print();
}

위 코드 예제에서 전위연산자인 경우 this 객체를 반환하는 데 반해 후위 연산자는 새로운 Point 객체를 반환했다. 반드시 그래야 하는 것은 아니지만 프로그램의 문맥에 맞게 작성해야 함을 유의하자.

#레퍼런스 변수

##포인터와 레퍼런스의 차이

###각가의 정의

  • 포인터: 메모리의 주소를 가지는 값. 즉 어떤 대상을 가리키는 값이다.
  • 레퍼런스: 메모리를 차지하고 있는 어떤 인스턴스에 대한 별칭. 즉 어떤 대상을 지칭하는 또하나의 이름이다.

###포인터는 아무 것도 가리키지 않을 수 있다. 레퍼런스는 아무 것도 아닌 것에 대한 별칭이 있을 수 없다

즉 포인터는 NULL 포인터라는 것이 존재한다. 하지만 NULL 레퍼런스는 말이 안된다. 이는 코딩 시 중요한 차이점이 있는데

Point *ppt;	// 오류 없음
Point &rpt;  // 오류

ppt는 초기화 하지 않고 코드를 작성하는 것이 가능하지만 rpt는 무엇에 대한 레퍼런스 인지 명시 해야 한다. 클래스인 경우에는 레퍼런스의 초기화는 생성자에서 할 수 있다.

###포인터의 값은 변경이 가능하지만 레퍼런스는 변경이 불가능하다

###레퍼런스 사용에 대한 지침

  • 만들어 지지 않을 수도 있는 객체를 사용한다면 포인터를 사용한다.
  • 값이 변할 수 있는 변수를 사용한다면 포인터를 사용한다.
  • 반드시 있는 객체를 다룬다면 레퍼런스를 사용한다.
  • 객체의 생성과 소멸 시기를 명확히 알 지 못한다면 포인터를 사용한다.

###레퍼런스의 사용 예

  • 연산자의 오버로딩 파라미터 객체의 변수를 레퍼런스로 사용하는 경우 가 많다.

코드예

const Point operator+(const Point& arg) const
{
	Point pt;
	pt.x = this-> x + arg.x;
	pt.y = this-> y + arg.y;

	return pt;
}

#참고문험

  • 뇌를 자극하는 C++ STL(공동환), 한빛미디어: 예제 코드의 많은 부분을 참고하여 수정하거나, 그대로 발췌하였습니다.
  • 이펙티브 C++(스캇 마이어스)
    • 1장: 포인터와 레퍼런스
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment