Chapter 01 C언어 기반의 C++


01-1. printf와 scanf를 대신하는 입출력 방식


- printf 대신 cout, scanf 대신 cin을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
int main()
{
    int num = 20;
    std::cout << "Hello World!" << std::endl;
    std::cout << "Hello " << "World!" << std::endl;
    std::cout << num << ' ' << 'A';
    std::cout << ' ' << 3.14 << std::endl;
    return 0;
}
cs



01-2 함수오버로딩


- 함수의 매개변수의 자료형 또는 개수가 다를 때, 동일한 이름의 함수정의를 허용하는 것을 말한다.

함수 오버로딩이 가능 하려면 매개변수의 자료형 또는 개수가 달라야 한다.



01-3 매개변수의 디폴트 값


- 매개변수에 디폴트 값이 설정되어 있으면, 함수호출 시 인자를 전달하지 않으면 디폴트 값이 전달된다.

- 매개변수에 디폴트 값이 설정되어 있으면, 선언된 매개변수의 수보다 적은 수의 인자전달이 가능하다. 그리고 전달되는 인자는 왼쪽에서부터 채워져 나가고, 부족분은 디폴트 값으로 채워진다.

- 함수의 원형을 별도로 선언하는 경우, 매개변수의 디폴트 값은 함수의 원형 선언에만 위치시켜야 한다.

- 일부분만 디폴트 값을 지정할 수도 있다. 하지만 반드시 오른쪽 매개변수의 디폴트 값부터 채우는 형태로 정의해야 한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
 
// 함수 원형을 별도로 선언하는 경우, 디폴트 값은 함수의 원형 선언에'만' 위치시켜야 한다.
// 매개변수에 전달되는 인자는 왼쪽부터 채워져 나가고, 부족분은 디폴트 값으로 채워진다.
int BoxVolume(int length, int width = 1int height = 1);    
 
int main()
{
    cout << "[3, 3, 3] : " << BoxVolume(333<< endl;
    cout << "[5, 5, D]" << BoxVolume(55<< endl;
    cout << "[7,D,D]" << BoxVolume(7<< endl;
//    cout << "[D,D,D]" << BoxVolume() << endl;    // 모든 매개변수에 디폴트 값이 지정된 것이 아니므로, 에러
    return 0;
}
 
int BoxVolume(int length, int width, int height)
{
    return length * width * height;
}
cs


1-4 인라인(inline) 함수


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
inline int SQUARE(int x)
{
    return x * x;
}
 
int main()
{
    std::cout << SQUARE(5<< std::endl;
    std::cout << SQUARE(12<< std::endl;
    return 0;
}
cs


- 매크로를 이용한 함수의 인라인화는 전처리기에 의해서 처리, 키워드 inline을 이용한 함수의 인라인화는 컴파일러에 의해서 처리된다.

- 따라서 컴파일러는 함수의 인라인화가 성능에 해가 된다고 판단할 경우, 키워드를 무시하기도 하고 필요한 경우 일부 함수를 임의로 인라인 처리하기도 한다.

- 템플릿을 이용하면 자료형에 의존적이지 않은 함수를 만들 수 있다.


01-5 이름공간(namespace)에 대한 소개

이름충돌을 막기 위해 namespace를 만들고 함수나 변수를 선언하여 사용한다.
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
#include <iostream>
 
// BestComImpl이라는 namespace 안에 함수 SimpleFunc를 정의
namespace BestComImpl
{
    void SimpleFunc()
    {
        std::cout << "BestCom이 정의한 함수" << std::endl;
    }
}
 
// ProgComImpl이라는 namespace 안에 함수 SimpleFunc를 정의
namespace ProgComImpl
{
    void SimpleFunc()
    {
        std::cout << "ProgCom이 정의한 함수" << std::endl;
    }
}
 
// ::을 가리켜 범위지정 연산자(scope resolution operator라 한다.
int main()
{
    BestComImpl::SimpleFunc();    
    ProgComImpl::SimpleFunc();    
    return 0;
}
cs


연산자 :: 을 가리켜 '범위지정 연산자'라 한다. namespace를 지정할 때 사용한다.

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
#include <iostream>
 
// BestComImpl이라는 namespace 안에 함수 SimpleFunc를 선언
namespace BestComImpl
{
    void SimpleFunc();
}
 
// ProgComImpl이라는 namespace 안에 함수 SimpleFunc를 선언
namespace ProgComImpl
{
    void SimpleFunc();
}
 
// ::을 가리켜 범위지정 연산자(scope resolution operator라 한다.
int main()
{
    BestComImpl::SimpleFunc();
    ProgComImpl::SimpleFunc();
    return 0;
}
 
// BestComImpl namespace에 선언된 함수 SimpleFunc를 정의
void BestComImpl::SimpleFunc()
{
    std::cout << "BestCom이 정의한 함수" << std::endl;
}
 
// ProgComImpl namespace에 선언된 함수 SimpleFunc를 정의
void ProgComImpl::SimpleFunc()
{
    std::cout << "ProgCom이 정의한 함수" << std::endl;
}
cs


namespace 기반에서 함수의 선언과 정의를 구분한다.


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
#include <iostream>
 
// BestComImpl이라는 namespace 안에 함수 SimpleFunc를 선언
namespace BestComImpl
{
    void SimpleFunc();
}
 
namespace BestComImpl
{
    void PrettyFunc();
}
 
// ProgComImpl이라는 namespace 안에 함수 SimpleFunc를 선언
namespace ProgComImpl
{
    void SimpleFunc();
}
 
// ::을 가리켜 범위지정 연산자(scope resolution operator라 한다.
int main()
{
    BestComImpl::SimpleFunc();
    return 0;
}
 
// BestComImpl namespace에 선언된 함수 SimpleFunc를 정의
void BestComImpl::SimpleFunc()
{
    std::cout << "BestCom이 정의한 함수" << std::endl;
    PrettyFunc();                // 동일 namespace
    ProgComImpl::SimpleFunc();    // 다른 namespace
}
 
// BestComImpl namespace에 선언된 함수 PrettyFunc를 정의
void BestComImpl::PrettyFunc()
{
    std::cout << "So Pretty!!" << std::endl;
}
 
// ProgComImpl namespace에 선언된 함수 SimpleFunc를 정의
void ProgComImpl::SimpleFunc()
{
    std::cout << "ProgCom이 정의한 함수" << std::endl;
}
cs


같은 namespace에 정의된 함수를 호출할 때에는 namespace를 명시할 필요가 없다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
namespace Hybrid
{
    void HybFunc()
    {
        std::cout << "So simple function!" << std::endl;
        std::cout << "In namespace Hybrid!" << std::endl;
    }
}
 
int main()
{
    using Hybrid::HybFunc;    // HybFunc 를 Hybrid namespace에서 찾으라는 일종의 선언
    HybFunc();
    return 0;
}
cs


using 키워드를 이용하여 HybFunc 함수를 호출할 때 namespace 범위 지정 없이 그냥 호출 할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
using std::cin;
using std::cout;
using std::endl;
 
int main()
{
    int num = 20;
 
    cout << "Hello World!!" << endl;
    cout << "Hello " << "World!" << endl;
    cout << num << ' ' << 'A';
    cout << ' ' << 3.14 << endl;
    return 0;
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
 
using namespace std;
 
int main()
{
    int num = 20;
 
    cout << "Hello World!!" << endl;
    cout << "Hello " << "World!" << endl;
    cout << num << ' ' << 'A';
    cout << ' ' << 3.14 << endl;
    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
34
35
36
37
38
#include <iostream>
using namespace std;
 
namespace AAA
{
    namespace BBB
    {
        namespace CCC
        {
            int num1;
            int num2;
        }
    }
}
 
int val = 100// 전역변수
 
void SimpleFunc()
{
    int val = 20;    // 지역변수
    val += 3;        // 지역변수 val의 값 3 증가
    ::val += 7;        // 전역변수 val의 값 7 증가
    cout << val << endl;
    cout << ::val << endl;
}
 
int main()
{
    AAA::BBB::CCC::num1 = 20;
    AAA::BBB::CCC::num2 = 30;
 
    namespace ABC = AAA::BBB::CCC;
 
    cout << ABC::num1 << endl;
    cout << ABC::num2 << endl;
    SimpleFunc();
    return 0;
}
cs




1
2
3
4
const int num = 10;         // 변수 num을 상수화
const int* ptr1 = &val1;     // 포인터 ptr1을 이용해서 val1의 값을 변경할 수 없음
int* const ptr2 = &val2;     // 포인터 ptr2가 상수화 됨, ptr2의 값을 변경할 수 없음
const int* const ptr3 = &val3;    // 포인터 ptr3가 상수화 되었으며, ptr3를 이용해서 val3의 값을 변경할 수 없음
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int val1 = 10;
int val2 = 20;
int main()
{
    const int* ptr1 = &val1;
    int* const ptr2 = &val2;
 
//    (*ptr1) = 20;    // 포인터 ptr1을 이용해서 val1의 값을 변경할 수 없음
    (*ptr2) = 30;
//    ptr2 = &val1;    // ptr2가 가리키는 주소를 변경할 수 없음, 즉 ptr2의 값을 변경할 수 없음
    printf("%d\n", val2);
}
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
34
35
36
#include <iostream>
using namespace std;
 
int main()
{
    int num1 = 1020;        // 변수 선언
    int &num2 = num1;        // 참조자 선언
 
    num2 = 3047;
 
    cout << "Val: " << num1 << endl;        // 3047
    cout << "Ref: " << num2 << endl;        // 3047
 
    cout << "Val: " << &num1 << endl;
    cout << "Ref: " << &num2 << endl;        // &num1 과 &num2의 값은 같다
                                            
    int &num3 = num2;                        // 참조자를 대상으로 참조자 선언
    cout << "num2: " << num2 << endl;
    cout << "num3: " << num3 << endl;
 
    // int &ref = 20;        // 참조자는 변수에 대해서만 선언 가능
    // int %ref;            // 참조자는 미리 선언했다가 후에 참조 불가, 참조 대상 변경 불가
    // int &ref = NULL;     // NULL로 초기화 불가
 
    int num = 12;
    int *ptr = &num;
    int **dptr = &ptr;
 
    int &ref = num;            // 변수 참조
    int *(&pref) = ptr;        // 포인터 변수 참조
    int **(&dpref) = dptr;    // 더블 포인터 변수 참조
 
    cout << ref << endl;
    cout << *pref << endl;
    cout << **dpref << endl;
}
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
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
#include <iostream>
using namespace std;
 
// Call-by-value 함수
// 주소 값을 이용해 함수의 외부에 선언된 변수에 접근하는 형태가 아님
int* SimpleFunc(int *ptr)
{
    return ptr + 1;
}
 
// Call-by-reference
void SwapByRef(int &ref1, int &ref2)
{
    int temp = ref1;
    ref1 = ref2;
    ref2 = temp;
}
 
// const로 참조자를 선언시, 참조자 ref를 통한 값의 변경을 허용하지 않음
void HappyFunc(const int &ref)
{
 
}
 
 
// 반환형이 참조형
int& RefRetFuncOne(int &ref)
{
    ref++;
    return ref;
}
 
// 반환형이 값
int RefRetFuncTwo(int &ref)
{
    ref++;
    return ref;
}
 
// 지역 변수를 참조형으로 반환하면 안된다.
int& RefRetFuncThree(int n)
{
    int num = 20;
    num += n;
    return num;
}
 
int main()
{
    int val1 = 10;
    int val2 = 20;
    SwapByRef(val1, val2);
    cout << "val1: " << val1 << endl;
    cout << "val2: " << val2 << endl;
 
 
    // 반환형이 참조형인 경우, 반환 값을 무엇으로 저장하느냐에 따라 결과에 차이가 있다.
    int num1 = 1;
    int &num2 = RefRetFuncOne(num1);    // 참조형으로 반환된 값을 참조자에 저장
    int num3 = RefRetFuncOne(num1);        // 참조형으로 반환된 값을 변수에 저장
 
    num1++;
    num2++;
    num3++;
    cout << "num1: " << num1 << endl;
    cout << "num2: " << num2 << endl;
    cout << "num3: " << num3 << endl;
 
    // 반환형이 값인 경우, 값이 반환되므로 반드시 변수에 저장해야 한다.
    int num4 = 1;
    int num5 = RefRetFuncTwo(num4);
 
    num4 += 50;
    num5 += 100;
    cout << "num4: " << num4 << endl;
    cout << "num5: " << num5 << endl;
 
    // int &num6 = RefRetFuncTwo(num4);        // 에러
 
    int &num7 = RefRetFuncThree(10);        // 지역 변수는 소멸되므로 참조형으로 반환하면 안된다.
    cout << "num7: " << num7 << endl;
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
 
int Adder(const int &num1, const int &num2)
{
    return num1 + num2;
}
 
int main()
{
    const int num = 20;
//    int &ref = num;                    // 에러 참조 불가
 
    const int &ref = num;            // 상수화된 변수에 대한 참조자 선언
 
    const int &ref2 = 50;            // 상수 참조 가능, 임시 변수 상수화
 
    cout << Adder(34<< endl;    // const의 상수 참조
}
cs


+ Recent posts