함수의 오버로딩, 생성자 정리

2023. 3. 19. 13:27개인공부/C++

함수의 오버로딩 (Overloading)

객체 지향 프로그래밍을 시작하기에 앞서 C++에 C와는 다른 새로운 기능이 있는데 바로 함수 오버로딩이다. C++에서는 같은 이름의 함수를 호출했을 때 사용하는 인자를 보고 구분해 준다. 즉 C++에서는 함수의 이름이 같더라도 인자가 다르면 다른 함수라고 판단하기 때문에 오류가 발생하지 않는다.

C++ 컴파일러에서 함수를 오버로딩하는 과정

1. 자신과 타입이  정확히 일치하는 함수를 찾는다.

2. 정확히 일치하는 타입이 없는 경우 아래와 같은 형변환을 통해서 일치하는 함수를 찾아본다.

* char, unsigned char, short 는 int로 변환된다.

* unsignde short 는 int의 크기에 따라 int 혹은 unsigned int로 변환된다.

*float 은 double 로 변환된다.

*enum 은 int로 변환된다.

3. 위와 같이 변환해도 일치하는 것이 없다면 아래의 좀 더 포괄적인  형변환을 통해 일치하는 함수를 찾는다.

*임의의 숫자(numeric) 타입은 다른 숫자 타입으로 변환된다. (ex float -> int)

*enum 도 임의의 숫자 타입으로 변환된다 (ex enum -> double)

* 0은 포인터 타입이나 숫자 타입으로 변환된 0은 포인터 타입이나 숫자 타입으로 변환된다.

*포인터는 void 포인터로 변환된다.

4. 유저 정의된 타입 변환으로 일치하는 것을 찾는다.

만약에 컴파일러가 위 과정을 통하더라도 일치하는 함수를 찾을 수 없거나 같은 단계에서 두 개 이상이 일치하는 경우 모호하다라고 판단해서 오류를 발생하게 된다.

C++ 생성 후 초기화를 도와주는 생성자(Constructor)

생성자는 기본적으로 "객체 생성시 자동으로 호출되는 함수"라고 볼 수 있다. 이 때 자동으로 호출되면서 객체를 초기화해주는 역할을 담당하게 된다. 객체를 초기화하는 역할을 하기 때문에 리턴값이 없다

정의 방법 => 클래스 이름 (인자) {} 로 선언 가능하다. 그리고 오버로딩을 이용해서 여러 가지 생성자를 만들 수 있다.

디폴트 생성자 (Default constructor)

처음에 생성자를 정의를 하지 않으면 디폴트 생성자가 호출이 된다. 디폴트 생성자는 인자를 하나도 가지지 않는 생성자인데, 클래스에 사용자가 어떠한 생성자도 명시적으로 정의하지 않았을 경우에 컴파일러가 자동으로 추가해 주는 생성자이다. 사용자가 어떤 다른 생성자를 추가한 순간 컴파일러는 자동으로 디폴트 생성자를 삽입하지 않는다 !!!!

아래에서 주의할 점은 date1 , date2는 인스턴스를 생성했지만 date3의 경우에는 리턴값이 Date이고 인자가 없는 함수를 정의하게 된 것으로 인식하기 때문에, 이는 암시적 표현으로 객체를 선언할 때 반드시 주의해 두어야 할 상황이다.

명시적으로 디폴트 생성자 사용하기 C++  11 이전에는 디폴트 생성자를 사용하고 싶을 경우 그냥 생성자를 정의하지 않는 방법 밖에 없었다 이 때문에 그 코드를 읽는 사용자 입장에서 개발자가 잊고 생성자를 정의를 안 한 것인지, 아니면 정말 디폴트 생성자를 사용하고파서 이런 것인지 알 길이 없다. C++11부터는 명시적으로 디폴트 생성자를 사용하도록 명시할 수 있다.

클래스() = default;

생각해보기

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
 
#include <iostream>
#include <vector>
 
#define infinite -987654321
 
class Point {
public:
    int x, y;
 
public:
    Point(int pos_x, int pos_y)
        :x(pos_x)
        ,y(pos_y)
    {}
};
 
class Geometry {
public:
    Geometry() {
        for (int i = 0; i < 100++i)
            point_array[i] = nullptr;
        num_points = 0;
    }
 
    void AddPoint(const Point& point) {
        point_array[num_points++= new Point(point.x, point.y);
    }
 
    // 모든 점들 간의 거리를 출력하는 함수 입니다.
    void PrintDistance();
 
    // 모든 점들을 잇는 직선들 간의 교점의 수를 출력해주 는 함수 입니다.
    // 참고적으로 임의의 두 점을 잇는 직선의 방정식을 f(x,y) = ax+by+c = 0
    // 이라고 할 때 임의의 다른 두 점 (x1, y1) 과 (x2, y2) 가 f(x,y)=0 을 기준으로
    // 서로 다른 부분에 있을 조건은 f(x1, y1) * f(x2, y2) <= 0 이면 됩니다.
    void PrintNumMeets();
 
private:
    // 점 100 개를 보관하는 배열.
    Point* point_array[100];
    int num_points;
};
 
int main()
{
    Geometry geo;
    geo.AddPoint(Point(23));
    geo.AddPoint(Point(44232));
    geo.AddPoint(Point(21323));
 
    geo.PrintDistance();
    geo.PrintNumMeets();
}
 
void Geometry::PrintDistance()
{
    for (int i = 0; i < num_points; ++i)
    {
        for (int j = i + 1; j < num_points; ++j)
        {
            double distance;
            // 피타고라스의 정리
            // pow(x,2) x의 2승,  sqrt() 제곱근
            distance = sqrt(pow(point_array[i]->- point_array[j]->x,2+ pow(point_array[i]->- point_array[j]->y,2));
            std::cout << " 점" << i + 1 << " 점" << j + 1 << " 의 거리는 " << distance << '\n';
        }
    }
}
 
void Geometry::PrintNumMeets()
{
    if (num_points < 3)
    {
        std::cout << "교점이 존재하지 않는다";
        return;
    }
    
    std::vector<std::pair<intint>> vec;  // 기울기, y절편
    for (int i = 0; i < num_points; ++i)
    {
        for (int j = i + 1; j < num_points; ++j)
        {
            Point* p1 = point_array[i];
            Point* p2 = point_array[j];
            int m;
            if (p2->!= p1->x)
                m = (p2->- p1->y) / (p2->- p1->x);
            else
                m = infinite;
            int n = p1->- m * p1->x;
            // 직선의 방정식 구하고 저장
            vec.push_back(std::make_pair(m, n));
 
        }
    }
 
    int ans = 0;
    // 직선간의 
    for(int i=0; i< vec.size(); ++i)
        for (int j = i + 1; j < vec.size(); ++j)
        {
            if (vec[i].first != vec[j].first)
                ++ans; // 교점 1개
            else if (vec[i].second == vec[j].second)         // 교점이 무수히 많음
            {
                std::cout << "교점이 무수히 많다.";
                return;
            }
        }
    std::cout << "교점은 " << ans << '\n';
 
}
 
cs

'개인공부 > C++' 카테고리의 다른 글

const, static 정리  (0) 2023.03.21
복사 생성자, 소멸자 정리  (0) 2023.03.20
객체 지향 프로그래밍 정리  (0) 2023.03.18
참조자 공부 내용 정리  (1) 2023.03.17
범위 기반 for 문(range-based for statement)  (0) 2023.03.14