본문 바로가기
프로그래밍/C || CPP

[C++ 정복하자] C에서 C++로 가기 위한 도약. [1]

by _BlankSpace 2017. 5. 14.

[C++ 정복하자] 를 위한 첫 번째 정리 포스팅입니다. 이 글은 제가 공부한 내용을 토대로 정리하는 글이므로, 원하시는 내용이나

보시는 분보다 낮은 실력일수도 있습니다. 부족하다고 생각하시는 점들은 댓글로 남겨주시면 최대한 보완하는 데 최선을 다하겠습니다.


목차로 돌아가기


 1C++에 대한 간단한 소개.

C++은 C언어를 포함합니다. 그러므로 C언어로 작성된 대부분의 프로그램은 C++ 컴파일러를 사용하더라도 컴파일이 가능합니다.

하지만, C++은 C언어가 가지고 있지 않은 문법적인 특성도 많이 가지고 있습니다. [예) 클래스와 구조체의 차이를 들 수 있습니다.]

이 중, 일부 특성들은 C++의 최대 특성인 객체지향적 특성의 반영을 위해서 C언어의 문법 구조가 자연스럽게 변한 것이라고 생각하면 됩니다.


2. C++의 새로운 입출력 방식.

흔히들, 프로그래밍 언어를 배울 때, 가장 먼저 하는 것이 화면에 "Hello World"일 것입니다. 이때, C에서 콘솔창에 문자열을 입출력하기 위해서 printf/scanf 함수를 사용하였습니다.

C++는 계속해서 printf/scanf 함수로 입출력을 할까라고 생각하는 사람이 있을텐데, 물론 다른 방법이 있습니다. 오히려, 우리가 생각할 것( 예를 든다면, 문자를 쓸 것인지 숫자를 쓸 것인지에 따른 형식자 지정) 등을 생각하지 않아도 되기 때문에, 우리에게는 편리함을 주는 cout/cin 이 등장합니다.

간단한 "Hello World"를 출력하는 예제로 cout/cin 사용 방법을 확인해보겠습니다.


HelloWorld.cpp

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

결과 :

 >> "Hello World"

 >> 15                  // 사용자가 입력한 숫자

 >> 15                  // 출력된 숫자


기존에 C를 학습했다면 위의 예제를 이해하는 데 큰 어려움을 없을 것입니다. 헤더파일이 바뀌었고, 출력 방법만 바뀌었다고 생각하면 될 것입니다. 다만, 위에서는 cout/cin만으로 입출력이 가능하다고 했는데 HelloWorld.cpp의 예제에서는 std::cout 또는 std::cin으로 표현된 것을 볼 수 있습니다. 이것은 cout과 cin을 c++ 표준 라이브러리(C++ Standard Library) 로 제공하고 있으므로, 사용자가 표준 라이브러리의 함수를 사용하고 있다라는 것을 컴퓨터에 알리는 것이라고 생각하면 되겠습니다.

즉, 나는 표준 라이브러리의 cin/cout 함수를 사용할 것입니다. 라는 것을 알리는 것으로 생각하면 된다는 말입니다. 그럼 cin/cout를 쓸 때마다 std::를 붙여줘야 하느냐 라는 의문이 드는 사람이 있을 수 있습니다.

답부터 말하자면 붙이지 않아도 됩니다. 그 방법은 나중에 설명하겠습니다.


혹시 여러 개의 변수를 입력 받고 싶으면 어떻게 해야 하나라고 생각할 수 있습니다. 방법은 간단합니다.

여러 개를 출력할 때는 "<<"을 연달아서, 입력할 때는 ">>"을 연달아서 쓰면 됩니다.

예)  std::cout<< "hello" << std::endl << "world";

std::cin >> num1 >> num2 >> num3;


[의문점 1]

보통 입출력이 가장 쉽다고 생각하는 학습자도 있겠지만, 미리 만들어진 함수가 없었다면 어땠을까? 보통, 콘솔에 출력한다는 게 생각은 쉬울 지 모르겠지만, 컴퓨터 안에서는 복잡하게 돌아갈 지 모른다. 이것에 대해서 찾아보자.


[의문점 2]

C++에서는 헤더 파일에 확장자를 붙이지 않는다. 이것은 표준 헤더파일의 선언에서는 확장자를 생략하기로 약속되어 있으므로 그런 것이라고 한다.


3. C++의 지역변수 선언.

C와 C++의 많은 차이점 중, 하나라고 할 수 있는 것은 지역변수를 선언하는 위치라고 할 수 있습니다. 기존의 C는 지역변수를 항상 제일 먼저 선언해야 했습니다. 이 점은 불편하지는 않았지만, 밑에 코드와 관련 있는 변수를 같이 묶어서 코딩하면 가독성이 높아질텐데.. 하고 아쉬움이 들만한 점이었습니다.

이러한 점을 C++에서 가능하게 만들었습니다. 다시 말해서, C++의 지역변수 선언은 함수 내 어디에든 넣어도 된다는 말입니다.

다음의 간단한 예로 확인해보겠습니다.


StaticEx1.cpp

1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
int main(void)
{
    int num1 = 5;
    std::cout << num1 << std::endl;
    int num2 = 10;
    std::cout << num2;
    return 0;
}
cs


결과:

 >> 5

 >> 10 


4. 간단한 함수 오버로딩(Function Overloading) 개념 익히기.

C언어에서 이름이 같은 함수를 정의했을 때, 결과는 어땠나요? 컴파일 에러가 났었죠.. 이게 객체지향 개념으로 넘어가면서, 허용되었다면 믿어지시나요? 물론, 정확히 같으면 안되겠죠. 근데 귀차니즘 가득한 프로그래머가 당연히 그러한 행동은 하지 않겠죠?

제가 말한 건 함수호출 시 전달되는 인자를 통해서 호출하고자 하는 함수가 구분 가능할 때를 말하는 것입니다. 그럴 듯 하지 않으신가요? 이런 것을 함수 오버로딩이라고 합니다.

다음 예제로 확실하게 개념을 파악해보겠습니다.


OverloadingEx1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
void ExFunc(int a)
{
    std::cout << "ExFunc(int a) called : " << a << std::endl;
}
 
void ExFunc(char a)
{
    std::cout << "ExFunc(char a) called : " << a << std::endl;
}
 
int main(void)
{
    ExFunc(5);
    ExFunc('B');
    return 0;
}
cs


결과:

 >> ExFunc(int a) called : 5

 >> ExFunc(char a) called : B


이해가 가셨나요? 인자의 자료형만 다른 데, 다르게 인식하여 결과 값도 의도한 대로 나오는 것을 확인할 수 있습니다. 다르게 인식하는 것은 매개변수의 개수가 다를 때, 자료형이 다를 때입니다.

하지만, 반환형이 다를 때는 기준이 될 수 없으니, 유의하셔서 사용하시면 좋을 것 같습니다.


5. 매개변수의 디폴트 값(Default Value).

C++ 함수에서는 인자 값을 정의에서 정할 수 있습니다. 이것을 '디폴트 값'이라고 합니다. 역시, 말로만 설명하면 뜬 구름 잡는 기분이겠죠? 이해를 도울 수 있도록 다음의 예제를 보겠습니다.


DefaultValueEx1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
int Exfunc(int num1=5int num2=10);
 
int main(void)
{
    Exfunc();
    Exfunc(15);
    Exfunc(1520);
    return 0;
}
 
int Exfunc(int num1, int num2)
{
    std::cout << "num1 : " << num1 << " num2 : " << num2 << std::endl;
}
cs


결과:

>> num1 : 5 num2 : 10

 >> num1 : 15 num2 : 10

 >> num1 : 15 num2 : 20


6번 라인을 보시면 결과는 초기 2번 라인에서 설정한 디폴트 값이 출력되는 것을 보실 수 있습니다. 근데 7번을 보시면 '15'라는 숫자 하나만 입력한 것을 볼 수 있습니다. 결과는 num1만 바뀐 것을 확인할 수 있습니다.

여기서 조심할 점은, 7번 라인과 같이 원래의 인자 개수보다 적게 값을 넣을 때는 앞에서부터 값이 들어간다는 것입니다. 이것은 함수에 전달되는 인자가 왼쪽에서부터 오른쪽 방향으로 채워지기 때문입니다. 따라서 이 점을 유의하여 사용해야 합니다.



6. 인라인(inline) 함수

C를 학습했다는 가정 하로 정리를 진행함으로써, 매크라 함수에 대해서는 따로 설명하지 않겠습니다. 매크로 함수에 대한 설명이 필요하신 분은 다음의 링크를 참고하시길 바랍니다.


매크로 함수 링크(아직 링크되어있지 않습니다.)


인라인 함수는 매크로 함수의 정의하기 복잡함을 단순화하고, 일반 함수처럼 정의 가능하도록 사용하기 위한, 즉 매크로 함수의 단점을 없애고자 만든 기능이라고 생각하면 됩니다.

인라인 함수는 함수의 실행 흐름이 다른 곳으로 이동했다가 돌아오는 것이 아닙니다. 즉, 하나의 함수 내에서 모두 처리하기 때문에 속도상의 이득을 볼 수 있습니다.

하지만, 프로그램의 크기가 커지겠죠. 이 말은 메모리가 한번에 많은 양의 데이터가 올라간다는 뜻입니다. 그로 인하여 Context Switching이 자주 일어날 수 있는 단점이 있습니다.


다음 예제로 사용법을 파악해보겠습니다.


InlineFunc.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
inline int ADD(int num1, int num2)
{
    return num1 + num2;
}
 
int main(void)
{
    std::cout << ADD(45<< std::endl;
    std::cout << ADD(1030<< std::endl;
    return 0;
}
cs


결과:

 >> 9

 >> 40 


7. 네임스페이스(namespace) 란? 


네임스페이스는 간단히 말하자면 주소라고 생각하면 되겠습니다. 우리 세계에선 이름으로 모든 사람을 구분할 수는 없습니다. 하지만 앞에 집 주소가 붙는다면 어떨까요? (설마 가족 중에 같은 이름이..!!!?) 뭐 그렇다면 어쩔수 없겠습니다만..

일반적인 상황에선 모든 사람을 구분할 수 있겠죠? 네임스페이스가 그러한 주소 기능이라고 생각하시면 되겠습니다.

간단한 예제를 보고, 이어서 설명하겠습니다.


NamespaceEx1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
namespace NamespaceEx1
{
    void NamespaceFunc(void)
    {   
        std::cout << "NamespaceEx1 입니다" << std::endl;
    }   
}
 
namespace NamespaceEx2
{
    void NamespaceFunc(void)
    {   
        std::cout << "NamespaceEx2 입니다" << std::endl;
    }   
}
 
int main(void)
{
    NamespaceEx1::NamespaceFunc();
    NamespaceEx2::NamespaceFunc();
    return 0;
}
cs


결과:

>> NamespaceEx1 입니다

 >> NamespaceEx2 입니다

예제를 보시면 의아해 하실만한 부분이 있습니다. 바로 네임스페이스 안에 정의되어있는 같은 이름의 함수죠. 당연히 불가능한 일이지만, 네임스페이스를 이용한다면 가능해집니다. 이처럼, 앞에 네임스페이스를 이용하여 같은 함수명도 구분하여 사용할 수 있습니다.


위에서 나중에 설명하겠다는 네임스페이스가 나왔는데요. 언제 그랬냐구요? "cin/cout를 쓸 때마다 std::를 붙여줘야 하느냐 라는 의문이 드는 사람이 있을 수 있습니다." 이 질문에서 말했습니다. 설마 까먹으셨을까요.. ㅋㅋ


이것은 다음의 방법으로 std::와 같이 네임스페이스를 따로 써주지 않아도 됩니다. 다음 예제를 보겠습니다.


UsingNamespaceEx.cpp

1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
using namespace std;
 
int main(void)
{
    cout << "이것은 namespace 기능 테스트 입니다." << endl;
    return 0;
}
 
cs


결과:

 >>  이것은 namespace 기능 테스트 입니다.



이상, C에서 C++로 가기 위한 도약. [1] 을 마치겠습니다. 계속해서 다음 포스팅인 C에서 C++로 가기 위한 도약. [2] 을 참고하시면 되겠습니다. 읽어주셔서 감사합니다.


참고 자료 : 윤성우의 열혈 C++ 프로그래밍

 구글링

 wiki 백과


목차로 돌아가기


제 글이 도움이 되셨거나 공감이 되시는 부분이 있으셨다면, 밑에 있는 공감 버튼 한 번씩 꾸욱 눌러주시면 감사하겠습니다.


공감 버튼은 저에게 큰 도움이 됩니다. 감사합니다.

댓글