티스토리 뷰

프로그래밍/C++

연산자 오버로딩

에어버스 2018. 6. 9. 14:42

람다함수호출 과련 기본지식

 

1. 연산자 오버로딩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
class Point
{
    int x, y;
public:
    Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
    Point operator+(Point& arg)
    {
        Point pt;
        pt.x = this->+ arg.x; // p1.x + arg.x 
        pt.y = this->+ arg.y;
        return pt;
    }
};
 
int main()
{
    Point p1(23), p2(55);
    Point p3 = p1.operator+(p2); 
    p3.Print();
    p3 = p1 + p2; // p1.operator+(p2) 처럼 살행됨
    p3.Print();
    _gettch();
    return 0;
}
cs

<실행>

2. 함수호출 연산자 오버로딩 - ()연산자

객체를 함수처럼 동작하게 한다.
27행 Print3는 함수 호출하는것이 아닌 객체로 ()연산자를 이용해서 마치 함수가 호출하는것 처럼 사용된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
struct FuncObject
{
public:
    void operator()(int arg)
    {
        cout << "정수 : " << arg << endl;
    }
};
 
void Print1(int arg)
{
    cout << "함수호출, 정수 : " << arg << endl;
}
 
int main()
{
    void (*Print2)(int= Print1; // 함수포인터
    FuncObject Print3;
    Print1(11); 
    Print2(22); 
    Print3.operator()(33);
    Print3(44); // Print3.operator()(44) 과 같음, 객체를 함수처럼 동작하게 하는 연산자
    _gettch();
    return 0;
}
cs

<실행> 

 

3. 배열 인덱스 연산자 오버로딩 - []연산자 오버로딩

많은 객체를 저장하고 관리하는 객체에 사용
반적으로, 컨테이너 객체에 사용하여 컨테이너 객체가 관리하는 내부 원소에 접근할때 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "stdafx.h"
#include <iostream>
 
using namespace std;
 
class Array {
    int *arr, size, capacity;
public:
    Array(int cap = 100) : arr(0), size(0), capacity(cap) {
        arr = new int[capacity];
    }
    ~Array() {
        delete[] arr;
    }
    void Add(int data) {
        if (size < capacity)
            arr[size++= data;
    }
    int Size() {
        return size;
    }
    int operator[] (int idx) {
        return arr[idx];
    }
};
 
int main()
{
    Array ar(10);
    ar.Add(10), ar.Add(20), ar.Add(30);
    for (int i = 0; i < ar.Size(); i++)
        cout << ar[i] << endl// ar[i] 는 일반 배열이 아닌 객체의 []연산자 이다
    _gettch();
    return 0;
}
cs



 <실행>

 

 

4. 메모리 접그, 클래스 멤버 접근 연산자 오버로딩 - *, -> 연산자

스마트포인터는 메모리 접근, 클래스 멤버 접근 기본 기능외에 메모리 해제를 자동으로 해준다.

아래 코드에서는 프로그램 실행 중에 함수가 종료되거나 에외 등이 발생하는 경우 delete p1, p2 가 실행되지 않아 메모리 누수가 발생할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Point {
    int x, y;
public:
    Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
};
 
int main()
{
    Point *p1 = new Point(23);
    Point *p2 = new Point(55);
    p1->Print();
    p2->Print();
    delete p1;
    delete p2;
    _gettch();
    return 0;
}
cs

아래 처럼 코드(8~15행)를 추가하면된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Point {
    int x, y;
public:
    Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
};
 
class PointPtr
{
    Point *ptr;
public:
    PointPtr(Point *p) : ptr(p) {}
    ~PointPtr() { delete ptr; }
    Point* operator->() { return ptr; }
};
 
int main()
{
    PointPtr p1 = new Point(23);
    PointPtr p2 = new Point(55);
    p1->Print();
    p2->Print();
    _gettch();
    return 0;
}
cs

<실행>

 

*연산자 오버로딩 (15행 추가)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Point {
    int x, y;
public:
    Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
};
 
class PointPtr
{
    Point *ptr;
public:
    PointPtr(Point *p) : ptr(p) {}
    ~PointPtr() { delete ptr; }
    Point* operator->() { return ptr; }
    Point& operator*() { return *ptr; }
};
 
int main()
{
    PointPtr p1 = new Point(23);
    PointPtr p2 = new Point(55);
    p1->Print();
    p2->Print();
    (*p1).Print();
    (*p2).Print();
    _gettch();
    return 0;
}
cs

<실행>

5. 생성자를 이용한 타입 변환

특정 타입을 인자로 받는 생성자가 있으면 생성자 호출을 통한 타입 변환이 가능하다. (객체 생성 후 대입)
생성자를 이용해 다른 타입을 자신의 타입으로 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class A{};
class B{
public:
    B() { cout << "B() 생성자" << endl; }
    B(A& _a) { cout << "B(A& _a) 생성자" << endl; }
    B(int n) { cout << "B(int n) 생성자" << endl; }
    B(double d) { cout << "B(double d) 생성자" << endl; }
};
 
int main()
{
    A a;
    int n = 10;
    double d = 5.5;
    B b;
    b = a; // b = B(a) 처럼 호출되어 B객체를 만들어 b 에 대입한다.
    b = n; // b = B(n)
    b = d;    // b = B(d)
    _gettch();
    return 0;
}
cs

<실행>

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Point {
    int x, y;
public:
    Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
};
 
int main()
{
    Point pt;
    pt.Print();
    pt = 10// Point(10, 0) 처럼 생성자 호출한다.
    pt.Print();
    _gettch();
    return 0;
}
cs


<실행>

이렇게 하면 프로그램은 실행되지만, 의도치 않게 Point 객체에 정수 값을 대입해도 컴파일이 되어 프로그램 실행 시 원하는 결과가 나오지 않는 문제가 있어, 생성자는 명시적 호출만 가능하다록 explicit 키워드를 사용한다.

4행 Point 앞에 explitcit 키워드를 추가하고 컴파일하면 12행 처럼 객체에 정수를 대입하면 오류가 난다.

(참고, pt = 10 //암시적 호출, pt = Point(10) // 명시적 호출)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Point {
    int x, y;
public:
    explicit Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
};
 
int main()
{
    Point pt;
    pt.Print();
    pt = Point(10); // explicit 키워드 사용하면 pt = 10 은 컴파일 에러 발생함 
    pt.Print();
    _gettch();
    return 0;
}
cs

<실행>

 

타입 변환 연산자 오버로딩을 이용한 타입 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class A {};
class B {
public:
    operator A() { 
        cout << "operator A() 호출" << endl;
        return A();
    }
    operator int() { 
        cout << "operator int() 호출" << endl;
        return 10;
    }
    operator double() {
        cout << "operator double() 호출" << endl;
        return 5.5;
    }    
};
 
int main()
{
    A a;
    int n;
    double d;
    B b;
    a = b; //b.operator A() 암시적호출
    n = b; //b.operator int() 암시적호출
    d = b; //b.operator double() 암시적호출
    cout << endl;
    a = b.operator A(); // 명시적호출
    n = b.operator int(); // 명시적호출
    d = b.operator double(); // 명시적호출
    _gettch();
    return 0;
}
cs

<실행>

타입 변환 연산자는 생성자나 소멸자처럼 반환 타입을 지정하지 않는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Point {
    int x, y;
public:
    explicit Point(int _x = 0int _y = 0) : x(_x), y(_y) {}
    void Print() { cout << x << ", " << y << endl; }
    operator int() { return x; }
};
 
int main()
{
    int n = 10;
    Point pt(23);
    n = pt; //pt.operator int() 암시적호출
    cout << n << endl;
    _gettch();
    return 0;
}
cs

<실행>

13행 처럼 정수형에 Point 객체를 대입하는 경우 첫번째 인자 값이 대입된다. (올바른 방법은 아닌듯...)

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31