시리즈:쉽게 배우는 프로그래밍 입문/C++: 두 판 사이의 차이

잔글 (문자열 찾아 바꾸기 - "어있" 문자열을 "어 있" 문자열로)
잔글 (봇: 자동으로 텍스트 교체 (-\[\[(File|file): +[[파일:))
 
(사용자 16명의 중간 판 63개는 보이지 않습니다)
1번째 줄: 1번째 줄:
{{쉽게 알 수 있다 시리즈|이 문서는 정말 쉽습니다.|문서의 내용이 너무 쉬워서 오늘부터 프로그래밍 수 있을 것 같습니다.}}
{{:시리즈:쉽게 배우는 프로그래밍 입문}}
[[분류:컴퓨터_프로그래밍]]
 
이번에는 [[C++]]에 대해서 배우실 차례입니다.
 
[[C++]]에 대한 설명은 리브레의 C++항목을 보시길 바랍니다.
 
본 문서에서는 파이썬과의 차이점을 들면서 C++을 알려드리겠습니다.
 
== 개발환경 설치 ==
본 강좌에서는 [[CodeBlocks]]라는 리눅스, 윈도우, 맥을 다 지원하는 C/C++용 IDE(컴파일러 + 편집기)을 사용할께요
=== 윈도우 ===
[http://sourceforge.net/projects/codeblocks/files/Binaries/13.12/Windows/codeblocks-13.12mingw-setup-TDM-GCC-481.exe 다운로드 링크] 을 눌러서 CodeBlocks를 설치하시면 됩니다.
=== 리눅스 ===
==== 우분투 ====
sudo apt-get install codeblocks를 입력하여 설치합니다.
=== OSX ===
[http://www.codeblocks.org/downloads/26 여기]에서 다운 받으면 됩니다.(개발자가 부족해서 16.01은 아직 안 된다고 하네요)
 
=== 코드블럭 실행 ===
[[파일:codeblocks-1.PNG]]
 
실행을 하면 이렇게 창이 뜹니다. 컴파일러를 선택하라는 창이지만 OK버튼을 눌러 다음으로 넘어 간다.
 
[[파일:codeblocks-2.PNG]]
 
다음은 소스파일과 프로젝트 파일 확장자를 코드블럭으로 연결할 것이냐는 질문이다.(C/CPP 코드블럭 프로젝트 파일등)
 
다른 컴파일러가 없을 경우 그냥 OK를 누르고, 없을 경우 1번째 체크박스을 선택한 후 OK버튼을 누른다.
 
[[파일:codeblocks-3.PNG]]
 
프로젝트를 생성할 경우 File -> New -> Project를 누르면 된다.
 
[[파일:codeblocks-4.PNG]]
 
Console Application을 누르고 OK를 누른다
 
[[파일:codeblocks-5.PNG]]
 
Next를 눌러 다음으로 넘어 간다.
 
[[파일:codeblocks-6.PNG]]
 
C++을 누르고 Next를 누른다.
 
[[파일:codeblocks-7.PNG]]
 
# 프로젝트 이름
# 프로젝트 폴더가 저장될 위치'''중요'''
# 실제 프로젝트가 저장될 위치
 
처음 만지는 분이 프로젝트 폴더가 저장될 위치를 지정하지 않고 Next를 눌러 꼬이는 경우가 많다. 꼭 파랑색 원이 그려진 버튼을 눌러서 폴더를 정한 다음에 Next를 누른다.
 
 
[[파일:codeblocks-8.PNG]]
 
완료가 되면 다음과 같이 프로젝트와 소스 파일 하나가 생긴다.
 
== Hello, World! ==
<syntaxhighlight lang=cpp>
#include <iostream>
 
int main(void)
{
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
</syntaxhighlight>
=== 파이썬과의 차이점 ===
 
우선 너무 달라서 공통점이 없어 보이기는 하지만 몇가지 공통점이 보인다
# 뭔가 친숙한 문자열인 "(쌍따옴표)가 보인다
# 뭔가 int라는 게 보인다.
하지만 차이점이 더 많이 보이는데 파이썬과 차이점을 보자면 다음과 같다.
# 파이썬에서 탭으로 구분했던 함수의 시작과 끝을 {}(중괄호)로 구분한다.
# 각 명령문이 끝나면 ;을 붙여야 한다.
# 함수 선언이 '''def'''로 시작하지 않는다.
이다.
 
우선 파이썬과 달리 C++는 프로그램의 '''시작점'''이라는 것이 필요하다. 파이썬의 경우 시작점이 코드의 첫줄이라면, C++의 프로그램의 시작점은 바로 '''이름이 main인 함수'''이다. 프로그램이 시작되면 main함수이 호출되고 프로그램이 동작한다.
 
또한 코드의 첫줄에 #include <iostream>이라는 문장이 보인다. 당장은 정확히 필요없이 '''터미널/콘솔에 출력하려면 필요하다'''라는 것만 알면 된다.
 
프로그램이 시작되면 main함수가 시작되므로 main함수 안을 보자. 한 문장만이 보인다.
<syntaxhighlight lang="cpp">
std::cout<<"Hello, World!"<<std::endl;
</syntaxhighlight>
std는 standard의 약자이며, cout은 console output이라는 약자이고. endl는 end line의 약자이다. 즉, std::cout은 표준으로 정해진 콘솔에 출력이라는 것이며, std::endl은 줄을 끝낸다, 즉 다음 줄로 넘어간다는 뜻이 된다.
 
== 변수==
C++의 변수와 파이썬의 변수는 그 의미와 사용용도는 같지만, 중요한 차이점이 몇가지 있다
# C++의 변수는 파이썬의 변수와 달리 '''선언'''이라는 것이 필요하다.
# C++의 변수는 파이썬의 변수와 달리 한번 정해진 데이터형(변수형)에서 바뀌지 않는다.
파이썬의 변수는 다음과 같이 선언하면 되었다.
<syntaxhighlight lang="python">
변수 = 1
</syntaxhighlight>
하지만 C++에서 변수는 다음과 같이 선언한다.
<syntaxhighlight lang="cpp">
int var = 1
</syntaxhighlight>
해석을 하자면 다음과 같다.
'''int라는 데이터 형인 var이라는 변수를 만들고, 1이라는 값을 넣는다.''' 또는 '''var은 1이고, 숫자다.'''<ref>저 숫자다 부분은 생략해서 생각하고 필요할 때 다시 떠올려 봐도 된다.</ref><ref>쉽게 해석했을 때</ref>
한편 이렇게 변수의 선언시 정해진 데이터형에서 다른 데이터형으로 중간에 바뀔 없다.
 
=== 데이터형 ===
C++는 컴퓨터와 매우 가까운 언어이다. 따라서 컴퓨터의 환경에 따라서 여러 가지가 바뀔 수 있는데, 데이터형이 특히 그러하다. 우선은 32비트를 기준으로 설명한 뒤, 64비트 CPU와 차이점이 있는 데이터형만 추가로 서술한다.
==== 정수형 ====
가장 많이 쓰이는 데이터형이다. 정수형이란, 소수점 아랫자리가 없는 데이터형을 말한다. 파이썬에서 정수형은 오직 크기가 하나밖에 없었지만, C++에서는 그 용도에 맞추어 사용하라는 뜻에서 다양한 크기를 가진 정수형이 존재한다.
{|class='wikitable' style='width:100%;'
|-
|style='text-align:center'|데이터형 이름
|style='text-align:center'|bool
|style='text-align:center'|char
|style='text-align:center'|short
|style='text-align:center'|int
|style='text-align:center'|long
|-
|style='text-align:center'|변수 크기
|style='text-align:center'|1비트(1바이트)
|style='text-align:center'|1바이트(8비트)
|style='text-align:center'|2바이트(16비트)
|style='text-align:center'|4바이트(32비트)
|style='text-align:center'|4바이트(32비트)
|-
|style='text-align:center'|표현가능 범위
|style='text-align:center'|false, true
|style='text-align:center'|-128 ~ 127
|style='text-align:center'|-32768~32767
|style='text-align:center'|-2147483648~2147483647
|style='text-align:center'|-2147483648~2147483647
|-
|style='text-align:center'|간단한 뜻
|style='text-align:center'|진위값
|style='text-align:center'|문자
|style='text-align:center'|작은 숫자
|style='text-align:center'|숫자
|style='text-align:center'|큰 숫자
|}
이중 long형의 경우 64비트 기계어로 번역될 경우에는 운영체제마다 그 크기가 다른데, 윈도우의 경우에는 4바이트, 리눅스의 경우에는 8바이트이다.
 
==== 실수형 ====
실수형이란 소수점이 붙은 수를 말한다. 컴퓨터에서 실수를 메모리에 저장할 때는 '''부동 소수점'''표기 방식을 사용한다.
 
'''부동소수점''' 이란 수학으로 보자면 지수방식으로 실수를 표기하는 것과 같다. 1.123123 x 10^2이런 식으로요, 다만 10^n승이 아니라 2^n으로 표기한다는게 차이점이다.
{|class='wikitable' style='width:100%;'
|-
|style='text-align:center'|변수명
|style='text-align:center'|float
|style='text-align:center'|double
|style='text-align:center'|long double
|-
|style='text-align:center'|데이터형 크기
|style='text-align:center'|4바이트
|style='text-align:center'|8바이트
|style='text-align:center'|8바이트 이상
|-
|}
==== 문자형 ====
String 형입니다. <code>string a="김바보"</code>이런 식으로 사용할 수 있습니다. 사실 String은 사용자 정의 타입이기 때문에 더 기능이 있는데, 나중에 알아보도록 합시다.
 
=== 형변환 ===
형변환(casting)은 다른 데이터형으로 변환하는 것을 말한다.
==== 묵시적 형변환 ====
묵시적 형변환이란 변수를 사용하여 셈을 할 때, 프로그래머가 코드로 ''값을 이 데이터형으로 바꿔라''라고 작성하지 않았지만 컴파일러가 ''이 값을 이 값이란 셈을 하려면 이런 데이터형으로 변환해야 하겠구나''라는 판단을 내리고 데이터형을 바꾸는 것을 말한다.
묵시적 형변환은 다음과 같은 우선 순위를 갖는다.
# double
# float
# long
# int
왜 다른 데이터형 bool, char, short은 없는가 하면 이들은 다른 데이터형과 셈을 때 int형으로 형변환이 된다.
==== 명시적 형변환 ====
<!--
묻지도 따지지도 않고 문법을 배우고 싶은 사람은 [[쉽게 배우는 프로그래밍 입문/C++/문법|문법]]을 읽으면 된다. 만약, 프로그래밍을 C++로 입문하고자 하는 사람이 있다면 [[쉽게 배우는 프로그래밍 입문/C++/따라하기|따라하기]]로.
== 이 언어를 배우려는 사람에게 전하는 주의사항 ==
== 이 언어를 배우려는 사람에게 전하는 주의사항 ==
만약 C 문법을 잘 모르는 경우 '''반드시''' [[쉽게 배우는 프로그래밍 입문/C]] 참고.
만약 C 문법을 잘 모르는 경우 '''반드시''' [[쉽게 배우는 프로그래밍 입문/C]] 참고.
12번째 줄: 184번째 줄:


=== <s>쓸데없이 불친절하고</s> 어려운 템플릿 ===
=== <s>쓸데없이 불친절하고</s> 어려운 템플릿 ===
템플릿은 메타프로그래밍 요소로, 서로 다른 여러가지의 클래스에 대해 '''각각을 따로 프로그래밍하지 않고 같은 이름을 가지는 대상(클래스, 함수)으로''' 프로그래밍할 수 있게 한다. 다시 말해서, '''일반화 프로그래밍'''이 가능하다! 하지만, C++의 템플릿은 다른 여타 언어들의 메타프로그래밍 요소와는 달리 [[템플릿 메타프로그래밍]]이라는 <s>변태짓</s>을 가능하게 한다.<s>나쁜 녀석들 같으니라고</s> <s>[[구글링]]을 해도 답이 안나온다</s> 이 기법은 C++ 프로그래머 중에서도 정말 고수들만이 제대로 활용할 수 있으므로, 공부하려고 마음먹었을 때 각오하는 것이 좋다.<s>하지만 우리 회사는 못하게 하는데</s> <s>그럴때는 실력에 대한 신뢰감을 줘야..</s>
템플릿은 메타프로그래밍 요소로, 서로 다른 여러 가지의 클래스에 대해 '''각각을 따로 프로그래밍하지 않고 같은 이름을 가지는 대상(클래스, 함수)으로''' 프로그래밍할 수 있게 한다. 다시 말해서, '''일반화 프로그래밍'''이 가능하다! 하지만, C++의 템플릿은 다른 여타 언어들의 메타프로그래밍 요소와는 달리 [[템플릿 메타프로그래밍]]이라는 <s>변태짓</s>을 가능하게 한다.<s>나쁜 녀석들 같으니라고</s> <s>[[구글링]]을 해도 답이 안나온다</s> 이 기법은 C++ 프로그래머 중에서도 정말 고수들만이 제대로 활용할 수 있으므로, 공부하려고 마음먹었을 때 각오하는 것이 좋다.<s>하지만 우리 회사는 못하게 하는데</s> <s>그럴때는 실력에 대한 신뢰감을 줘야..</s>


=== 함수형 프로그래밍은 또 어디에서 굴러들어온건데? ===
=== 함수형 프로그래밍은 또 어디에서 굴러들어온건데? ===
45번째 줄: 217번째 줄:
== <s>예외란 없다</s>Hello, World! ==
== <s>예외란 없다</s>Hello, World! ==
빈 프로젝트를 생성한 후 소스(.cpp)파일에 다음 내용을 작성한다.
빈 프로젝트를 생성한 후 소스(.cpp)파일에 다음 내용을 작성한다.
<source lang=cpp>
<syntaxhighlight lang=cpp>
#include <iostream>
#include <iostream>


int main()
int main(void)
{
{
     std::cout << "Hello, World!" << std::endl;
     std::cout << "Hello, World!" << std::endl;
    return 0;
}
}
</source>
</syntaxhighlight>




혹은 이렇게도 쓸 수 있다.  
혹은 이렇게도 쓸 수 있다.  


<source lang=cpp>
<syntaxhighlight lang=cpp>
#include <iostream>
#include <iostream>
using namespace std;
using namespace std;
int main()
int main(void)
{
{
     cout << "Hello, World!" <<endl;
     cout << "Hello, World!" <<endl;
    return 0;
}
}
</source>
</syntaxhighlight>
 
 
설명: C언어에서는 헤더파일에 stdio.h를 선언했을텐데, 이와 유사한 일을 하는 헤더파일이 C++의 iostream이다. 그리고 여기에는 c++헤더파일이 아니라 c헤더파일(stdio.h 혹은 stdlib.h 같은)을 선언해도 되며, 선언만 했다면 c언어의 함수도 그대로 쓸 수 있다. 그러나 우리가 배우려는건 c++이므로 iostream에 들어 있는 함수를 알아보자.


cout이라는 함수가 쓰였는데, 이것은 << 뒤에 있는 내용을 출력하는 함수이다. <<뒤에는 문자열, 정수, 실수, 문자 등이 올 수 있다. 또한 endl은 '개행'을 뜻하는 함수이다. 즉
또는


std::cout<<"Hello World"<<std::endl;
<syntaxhighlight lang=cpp>
 
#include <cstdio>
은 다음 문장과 완벽하게 똑같다.
int main(void)
 
std::cout<<"Hello World\n";
 
이쯤에서 cout 앞에 쓰인 std라는 것의 용도가 궁금할 것이다. 이것은 이름공간(name space)라는 것인데, 쉽게 말하자면 cout과 endl이라는 함수가 std라는 이름공간안에 들어 있는 것이다. 즉 std::cout은 'std 이름공간 안에 들어 있는 cout'이라는 의미이다. 하지만 많은 사람들은 std::cout이라고 치는 것을 귀찮아하는데, 그래서 두번째 코드에는
 
using namespace std;
 
라고 적혀있는 것이다. 이것은 'std에 들어 있는 함수는 이름공간을 생략하고 쓰겠다'라는 선언이다.
 
하지만 별로 좋은 코딩 습관은 아니니 위처럼 std::를 꼬박꼬박 붙여주자.
 
== 새 표준 입출력 ==
iostream을 인클루드하고 사용한다. 표준 라이브러리에서는 더 이상 C에서 쓰이던 확장자 h를 쓰지 않는다. C++ 라이브러리 헤더는 그대로 확장자 없이 쓰면 되며, C 헤더의 경우는 cstdio처럼 앞에 c를 붙인채 사용하면 된다. 이름 공간은 std.
=== 표준 출력 ===
<source lang=cpp>
std::cout << [기본 자료형 변수/상수];
</source>
기본적으로 이 형식으로 사용한다. 기본 자료형이 아닌 구조체, 클래스 등은 후술할 [[오버로딩]] 참고.
 
<source lang=cpp>
std::cout << [출력 대상] << [출력 대상] << ...
</source>
이렇게 여러 대상의 출력을 한 줄에 작성할 수 있다.
 
<source lang=cpp>
std::cout << ... << std::endl;
</source>
이렇게 작성하면 중간의 출력대상을 모두 출력한 후 한 줄을 강제 개행한다.
=== 표준 입력 ===
 
== 상수 ==
기존의 const에 더해, volatile과 mutable 키워드를 사용할 수 있게 되었다. mutable 키워드의 경우 후술할 클래스 부분을 참고.
 
volatile 키워드를 사용한 변수는 그 값이 언제든지 바뀔 수 있다는 것을 컴파일러에게 명시적으로 전달해주기 때문에, 최적화를 방해한다. goto 키워드처럼 '''쓰면 방해되는''' 키워드이기 때문에 이런 키워드는 없다고 생각하고 프로그래밍하자.
 
== 좌측값, 우측값 ==
C++11이 제정되며 강조되는 개념이다. '''절대로 없던게 아니다!''' C부터 있던 유서깊은(?) 개념이다.
 
좌측값(L-Value)는 변수나 변수의 주소 등 확실하게 ''메모리에 위치한 주소''를 가진 변수이다. C에서 사용되던 일반적인 변수를 떠올리면 된다. 반면, 우측값(R-Value)는 그 외의 모든 ''임시변수''와 ''메모리에 위치하지 않은 것들''인 상수를 포함한다. 임시변수에 대한 자세한 개념은 [[추가바람]]. 더욱 엄밀하게 말하자면, 좌측값은 '''식 한 줄이 실행된 후에도 남아있는 값'''이고, 우측값은 '''식 한 줄이 실행되고 나면 소멸하는 값'''이다.
 
사실, 좌측값, 우측값이란 이름은 대입 연산자를 기준으로 올 수 있는 방향에 따라 지어졌다. 좌측값은 대입 연산자 왼쪽, 오른쪽 다 올 수 있지만, '''우측값은 오른쪽에만''' 올 수 있다. 따라서, 대입 연산자 '''왼쪽에는 좌측값만''' 올 수 있다. 또한, 좌측값은 메모리상에 위치한 주소가 정해져 있으므로 변수로 선언할 수 있지만, 우측값은 그러지 못한다. 그러나, 함수의 인자로 오거나 반환값으로 오는 것은 가능하다. 앞으로 후술할 템플릿에도 사용할 수 있다.
 
이 개념을 직접 언어적 측면에서 도입함으로써, C++은 임시변수의 생성을 위한 메모리와 시간을 절약할 수 있게 되었다.
 
== 레퍼런스 ==
대놓고 이름만 봐도 참조에 의한 호출(Call-by-Reference)<ref>주소를 저장하는 변수의 종류인 포인터, 레퍼런스를 이용해서 그 주소에 위치한 값을 호출하는 방식, 값에 의한 호출(Call-by-Value)와는 반대개념</ref>에서 사용하기 위해 만들어낸 개념이라는 것을 알 수 있다. 포인터가 있는데 굳이 레퍼런스를 만든 이유는, 포인터 자체가 가진 특수성 때문이다. 포인터는 메모리에 직접 접근하는 것이나, 프로그래머의 실력이 출중하지 않은 이상은 포인터 오류에 걸리기가 매우 쉽고, 또 그 사용법상 여러가지 문제(예를 들어 Dangling pointer) 등을 초래할 수 있다. 때문에 현대 프로그래밍 언어들에서는 대부분 이러한 방식을 사용하지 않고, 레퍼런스 방식으로 안전한 접근을 유도하는데, C++에서도 포인터 접근 대신에 안전한 레퍼런스 접근(내부 구현은 포인터와 비슷하다)을 제공한 것이다.
 
사용법을 포인터와 비교하면 다음과 같다.
<source lang=cpp>
int q;
int *p;// 포인터, 가능
int &p;// 레퍼런스, 불가능, 선언시 초기화해야 함
int *p = &q;// 포인터, 가능
int &p = q;// 레퍼런스, 가능
</source>
 
가장 많이 쓰이는, 함수에서의 사용 예는 다음과 같다.
<source lang=cpp>
int f(const int n);// 임시값, 반환도 임시값
int f(const int& n);// 좌측값, 반환은 임시값
int f(const int&& n);// 우측값, 반환은 임시값
 
int& f(const int n);// 임시값, 반환은 좌측값
int& f(const int& n);// 좌측값, 반환도 좌측값
int& f(const int&& n);// 우측값, 반환은 좌측값
 
int&& f(const int n);// 임시값, 반환은 우측값
int&& f(const int& n);// 좌측값, 반환은 우측값
int&& f(const int&& n);// 우측값, 반환도 우측값
</source>
 
== 이름공간 ==
그동안 사용하던 static 키워드에서 탈피할 수 있게 해주는 표준 문법이다. static은 해당 파일에서만 전역인 것처럼 사용할 수 있게 하였지만, 이름공간은 무려, 인클루드만 해주면 '''어디에서나''' 사용할 수 있다! 심지어 변수, 함수, 클래스 등을 '''용도별로''' 모을 수도 있다. 거기에 확장도 가능하니 [[금상첨화]].
 
사실 이름 공간은 그런 목적으로 고안된 것이다. 라이브러리들이 많아지고, 이 라이브러리들 사이에서 이름이 겹치는 경우가 발생할 수 있다보니, 아무리 오버로딩을 지원하는 C++이지만 한계가 있을 수 있고, 그래서 라이브러리별로 각자 다른 이름공간을 주어 구성할 수 있게 한 개념이다. 대조되는 개념으로 Java의 package 등이 있다.
 
가장 대표적인 이름공간으로는 C++ 표준 라이브러리의 이름공간인 std가 있다.
 
용법은 다음과 같다.
<source lang=cpp>
namespace A{  // 여기까지가 namespace 시작부분
}  // 여기만 namespace 종결부분
 
namespace B{
    int V;
    int func() { }
    class C;
    enum E {};
}
B::V = 1;  // 접근자([이름공간명]::[멤버명])를 사용한 내부 멤버 접근
using B::func; // 내부 멤버를 현재 범위 내에서 접근자를 사용하지 않고 접근 가능
using namespace B; // 내부 멤버 전체를 현재 범위 내에서 개방
 
namespace{ }  // 이름이 없는 경우, 전역취급. 접근자는 이름이 없으므로 ::[멤버명]
</source>
 
== 공용체, 열거형 ==
공용체의 경우 클래스와 비슷하게 생성자와 소멸자를 사용할 수 있게 되었고, 이름없는 공용체도 만들 수 있다. 다만, C 수준에서 공용체를 다룰 기회가 좀 있었던 것에 비하면, C++의 경우 대부분 low-level 부분에 C 라이브러리를 쓰는 경우가 많아 C++에서 확장된 공용체를 쓸 일은 거의 없다.
 
열거형은 열거 클래스라는 기존 열거형을 확장한 형태를 사용할 수 있게 되었다.
<source lang=cpp>
enum class A : int
{
{
     FIRST = 1,
     printf("Hello, World!");
    SECOND = 2
    return 0;
};
</source>
 
== 객체 ==
C언어의 구조체(struct)를 기억하는가? C언어의 구조체는 다음과 같은 구조이다.
 
<source lang=cpp>
struct A
{
int x;
int y;
};
</source>
 
즉 구조체 안에는 변수를 선언할 수 있다. 그런데 C++에서는 struct에 변수 뿐만 아니라 함수의 선언도 허용하고 있다. 즉 다음과 같은 코딩이 가능하다.
 
 
<source lang=cpp>
#include<iostream>
 
struct A
{
int x;
int y;
void func(){
std::cout<<x<<y<<std::endl;
}
};
 
int main()
{
A a={1, 2};
a.func();
return 0;
}
}
</source>
</syntaxhighlight>


이 코드를 자세히 보면 struct 내부에 함수의 선언이 가능할 뿐만 아니라, 구조체 자료형의 선언 방법도 C와 다르다. C에서라면 struct A a라고 선언했겠지만, C++에서는 A a라고 선언하는 것을 허용한다. 또한 struct A 내부의 함수인 func는 main 함수에서 마치 구조체 내부의 변수처럼 a 뒤에 점(.)만 찍으면 접근할 수 있다.
이것이 C++에서 struct의 새로운 기능이다. 또한 여기서 a와 같은 것들을 객체(오브젝트)라고 부른다.
한편 c++에서는 '접근지정자'라는 것을 struct 안에 넣을 수 있다. 다음 코드를 보자.


설명: C언어의 stdio와 같이 표준 입출력을 담당하는 C++의 헤더는 iostream이다.
C++는 C언어와는 차이점이 존재하는데 표준 입출력에서 '함수'가 아닌 '(여러 함수를 포함하는)객체'를 사용한다는 점이다.
C언어를 사용해오던 개발자가 C++를 처음 접할 때 생소함을 느끼는 이유가 그것이다.


<source lang=cpp>
참고로 C++는 C언어와 상위호환이 가능한 언어로 설계되어 기존의 C표준 헤더를 사용하는 것이 가능하다.
#include<iostream>
비교적 최근의 C++표준은 헤더 명 앞에 c를 붙이고 확장자를 지워서 stdio.h를 cstdio와 같이 쓴다.
예제 코드는 세 번째 소스코드를 참조하면 된다.


struct A
C++ 표준 입출력에서는 입출력을 위한 여러 객체나 함수를 제공하는데 대표적으로 cout, cin, endl등이 있다.
{
위의 소스코드에서 쓰인 cout객체는 콘솔 화면 상에 문자열을 출력하는 기능을 가지고 있다(cout를 console out로 이해하면 편하다). cout 객체의 사용방법은 cout객체와 출력하려는 대상을 << 연산자로 연결하는 것이다.
private:
출력 대상에는 문자열, 정수, 실수, 문자 등이 있고 << 연산자는 비트연산자가 아님을 주의한다.
int x;
또한 endl은 개행(endl을 end line으로 이해하면 편하다)의 기능을 하는 객체이다.
int y;
이 객체는 cout 객체 뒤에 전달할 수 있으며 이스케이프 시퀀스 \n로 대체가 가능하다(물론 따옴표 안에 묶어야 한다).
public:
따라서
void func(){
std::cout<<x<<y<<std::endl;
}
};


int main()
<syntaxhighlight lang=cpp>
{
std::cout<<"Hello World"<<std::endl;
A a={1, 2};
</syntaxhighlight>
        /*
        a.x=0;
        */
        //↑ 컴파일 에러 발생
a.func();
return 0;
}
</source>


이 코드에서는 a.x에 0을 대입하면 컴파일 오류가 뜨는데, private는 아래에 선언된 변수와 함수들이 오직 같은 struct 내부에서만 접근 가능하도록 한다. 따라서 func함수는 x와 y에 접근할 수 있지만 이 struct 밖에 있는 main 함수에서는 x에 접근할 수 없는 것이다. public은 아래에 선언된 변수와 함수들이 struct 밖에서도 접근 가능하도록 한다. 또한 private와 public 외에도 protected라는 것이 있는데, 이것은 상속을 배우고 나서야 이해되는 개념이니 일단은 더이상의 자세한 설명은 생략하겠다.
은 다음 문장과 완벽하게 똑같다.


그리고 c++에서는 struct 대신에 class라고 쓸 수 있다.
<syntaxhighlight lang=cpp>
즉 위의 코드를
std::cout<<"Hello World\n";
</syntaxhighlight>


<source lang=cpp>
이쯤에서 cout 앞에 쓰인 std라는 것의 정체가 궁금할 것이다. 이것은 이름공간(name space)라는 것인데, 여러분들이 정의한 객체나 함수가 헤더에 존재하는 것과 이름이 중복된다면 곤란해지므로 이것을 방지하기 위해 만들어진 개념이다.
#include<iostream>
이름공간안에 묶인 객체나 함수를 사용하기 위해서는 항상 앞에 이름공간의 경로를 명시해야 하며 경로를 연결하는 연산자는 :: 연산자이다.
class A
{
private:
int x;
int y;
public:
void func(){
std::cout<<x<<y<<std::endl;
}
};


int main()
std::를 일일이 붙이는 것도 꽤 번거로운 일이지만 이는 어느 정도 감수할 있다.
{
그러나 cout객체의 경로가 aaa::bbb::ccc::ddd::eee라고 한다면 번거로운 것은 물론이고 가독성까지 떨어지기 때문에 적당한 생략이 필요하다. 그래서 존재하는 것이 바로 using 이다. 이름 공간의 경로를 using 하나만 사용한다면 통째로 생략하는 게 가능해진다.
A a={1, 2};
        a.func();
return 0;
}
</source>
 
이렇게도 쓸 있는 것이다. 단지 struct를 class로 교체한 것 뿐이지만, 두 코드는 완벽하게 기능이 똑같다. 물론 struct와 class에도 기능의 차이는 있는데, struct는 기본으로 설정된 접근지정자가 public이지만 class는 private이다.
 
 
<source lang=cpp>
struct A
{
int x;
int y;
};
</source>
 
위의 코드는
 
<source lang=cpp>
struct A
{
public:
int x;
int y;
};
</source>
 
 
<source lang=cpp>
class A
{
public:
int x;
int y;
};
</source>
 
이 두 코드와 완전하게 같은 기능을 가지며,
 
<source lang=cpp>
class A
{
int x;
int y;
};
</source>
 
위의 코드는
 
<source lang=cpp>
class A
{
private:
int x;
int y;
};
</source>


앞의 예제를 보면


using namespace std;


<source lang=cpp>
라고 적혀 있을 것이다. 이것은 '이름공간 std에 들어 있는 모든 객체나 함수는 이름공간을 생략하고 쓰겠다'라는 선언이다.
struct A
하지만 using을 남용하면 이름 충돌 위험성이 있기 때문에 별로 좋은 코딩 습관은 아니다.
{
위처럼 std::를 꼬박꼬박 붙여주거나 사용할 객체만 골라서 using std::cout; 와 같이 선언하면 된다.
private:
int x;
int y;
};
</source>


이 두 코드와 완벽하게 같은 기능을 제공한다. 차이는 오직 이것 뿐이다.
== 데이터형 ==
== 제어문 ==
== 함수 ==
== 참조형(레퍼런스) ==
=== 포인터와 참조형의 차이 ===


== 동적할당 ==
== 객체지향 기초 ==
=== struct ===
=== struct의 확장 class ===
==== 구조체에 함수를 추가 ====
=== 생성자와 소멸자 ===


=== 용어 ===
=== 접근지정자 ===
=== 접근지정자 ===
=== const 멤버 ===
=== static 멤버 ===
=== 생성자 ===
==== 일반 생성자 ====
==== 복사 생성자 ====
==== 이동 생성자 ====
=== 소멸자 ===
=== 연산자 오버로딩 ===
=== 상속 ===
==== 명시적 상속 ====
==== 암시적 상속 ====
==== 다중상속 ====
=== 동적 생성 ===


== 예외처리 ==
== 예외처리 ==
=== 원리 ===
=== 사용법 ===
== 템플릿 ==
<s>컴파일 타임을 잡아먹는 주범</s>
일반화 프로그래밍을 다룬다. [[템플릿 메타프로그래밍]]은 해당 항목 참조.
=== 템플릿 함수 ===
=== 템플릿 클래스 ===
== 람다 ==
=== 람다의 전신, 함수자 ===
=== 람다와 함수 포인터 ===
=== 람다의 사용법 ===
== 고급 과정 ==
== 고급 과정 ==
 
* [[C++/STL|STL]]
* [[C++/CLI]]
-->
{{각주}}
{{각주}}
{{쉽게 배우는 프로그래밍 입문}}
[[분류:프로그래밍 시리즈|C++]]
[[분류:C++]]

2022년 8월 28일 (일) 23:30 기준 최신판

문서의 내용이 너무 쉬워서 오늘부터 프로그래밍 할 수 있을 것 같습니다.

이 문서에는 독자적으로 연구한 내용이 들어갑니다. 다른 사람의 의견을 존중하면서 무례하지 않도록 작성해 주시고, 의견 충돌 시 토론 문서에서 토론해 주세요.
리브레 프로그래밍 시리즈
초급
프로그래밍
중급
프로그래밍
고급
프로그래밍
Python
협업


이번에는 C++에 대해서 배우실 차례입니다.

C++에 대한 설명은 리브레의 C++항목을 보시길 바랍니다.

본 문서에서는 파이썬과의 차이점을 들면서 C++을 알려드리겠습니다.

개발환경 설치[편집 | 원본 편집]

본 강좌에서는 CodeBlocks라는 리눅스, 윈도우, 맥을 다 지원하는 C/C++용 IDE(컴파일러 + 편집기)을 사용할께요

윈도우[편집 | 원본 편집]

다운로드 링크 을 눌러서 CodeBlocks를 설치하시면 됩니다.

리눅스[편집 | 원본 편집]

우분투[편집 | 원본 편집]

sudo apt-get install codeblocks를 입력하여 설치합니다.

OSX[편집 | 원본 편집]

여기에서 다운 받으면 됩니다.(개발자가 부족해서 16.01은 아직 안 된다고 하네요)

코드블럭 실행[편집 | 원본 편집]

Codeblocks-1.PNG

실행을 하면 이렇게 창이 뜹니다. 컴파일러를 선택하라는 창이지만 OK버튼을 눌러 다음으로 넘어 간다.

Codeblocks-2.PNG

다음은 소스파일과 프로젝트 파일 확장자를 코드블럭으로 연결할 것이냐는 질문이다.(C/CPP 코드블럭 프로젝트 파일등)

다른 컴파일러가 없을 경우 그냥 OK를 누르고, 없을 경우 1번째 체크박스을 선택한 후 OK버튼을 누른다.

Codeblocks-3.PNG

프로젝트를 생성할 경우 File -> New -> Project를 누르면 된다.

Codeblocks-4.PNG

Console Application을 누르고 OK를 누른다

Codeblocks-5.PNG

Next를 눌러 다음으로 넘어 간다.

Codeblocks-6.PNG

C++을 누르고 Next를 누른다.

Codeblocks-7.PNG

  1. 프로젝트 이름
  2. 프로젝트 폴더가 저장될 위치중요
  3. 실제 프로젝트가 저장될 위치

처음 만지는 분이 프로젝트 폴더가 저장될 위치를 지정하지 않고 Next를 눌러 꼬이는 경우가 많다. 꼭 파랑색 원이 그려진 버튼을 눌러서 폴더를 정한 다음에 Next를 누른다.


Codeblocks-8.PNG

완료가 되면 다음과 같이 프로젝트와 소스 파일 하나가 생긴다.

Hello, World![편집 | 원본 편집]

#include <iostream>

int main(void)
{
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

파이썬과의 차이점[편집 | 원본 편집]

우선 너무 달라서 공통점이 없어 보이기는 하지만 몇가지 공통점이 보인다

  1. 뭔가 친숙한 문자열인 "(쌍따옴표)가 보인다
  2. 뭔가 int라는 게 보인다.

하지만 차이점이 더 많이 보이는데 파이썬과 차이점을 보자면 다음과 같다.

  1. 파이썬에서 탭으로 구분했던 함수의 시작과 끝을 {}(중괄호)로 구분한다.
  2. 각 명령문이 끝나면 ;을 붙여야 한다.
  3. 함수 선언이 def로 시작하지 않는다.

이다.

우선 파이썬과 달리 C++는 프로그램의 시작점이라는 것이 필요하다. 파이썬의 경우 시작점이 코드의 첫줄이라면, C++의 프로그램의 시작점은 바로 이름이 main인 함수이다. 프로그램이 시작되면 main함수이 호출되고 프로그램이 동작한다.

또한 코드의 첫줄에 #include <iostream>이라는 문장이 보인다. 당장은 정확히 알 필요없이 터미널/콘솔에 출력하려면 필요하다라는 것만 알면 된다.

프로그램이 시작되면 main함수가 시작되므로 main함수 안을 보자. 한 문장만이 보인다.

std::cout<<"Hello, World!"<<std::endl;

std는 standard의 약자이며, cout은 console output이라는 약자이고. endl는 end line의 약자이다. 즉, std::cout은 표준으로 정해진 콘솔에 출력이라는 것이며, std::endl은 줄을 끝낸다, 즉 다음 줄로 넘어간다는 뜻이 된다.

변수[편집 | 원본 편집]

C++의 변수와 파이썬의 변수는 그 의미와 사용용도는 같지만, 중요한 차이점이 몇가지 있다

  1. C++의 변수는 파이썬의 변수와 달리 선언이라는 것이 필요하다.
  2. C++의 변수는 파이썬의 변수와 달리 한번 정해진 데이터형(변수형)에서 바뀌지 않는다.

파이썬의 변수는 다음과 같이 선언하면 되었다.

변수 = 1

하지만 C++에서 변수는 다음과 같이 선언한다.

int var = 1

해석을 하자면 다음과 같다. int라는 데이터 형인 var이라는 변수를 만들고, 1이라는 값을 넣는다. 또는 var은 1이고, 숫자다.[1][2] 한편 이렇게 변수의 선언시 정해진 데이터형에서 다른 데이터형으로 중간에 바뀔 수 없다.

데이터형[편집 | 원본 편집]

C++는 컴퓨터와 매우 가까운 언어이다. 따라서 컴퓨터의 환경에 따라서 여러 가지가 바뀔 수 있는데, 데이터형이 특히 그러하다. 우선은 32비트를 기준으로 설명한 뒤, 64비트 CPU와 차이점이 있는 데이터형만 추가로 서술한다.

정수형[편집 | 원본 편집]

가장 많이 쓰이는 데이터형이다. 정수형이란, 소수점 아랫자리가 없는 데이터형을 말한다. 파이썬에서 정수형은 오직 크기가 하나밖에 없었지만, C++에서는 그 용도에 맞추어 사용하라는 뜻에서 다양한 크기를 가진 정수형이 존재한다.

데이터형 이름 bool char short int long
변수 크기 1비트(1바이트) 1바이트(8비트) 2바이트(16비트) 4바이트(32비트) 4바이트(32비트)
표현가능 범위 false, true -128 ~ 127 -32768~32767 -2147483648~2147483647 -2147483648~2147483647
간단한 뜻 진위값 문자 작은 숫자 숫자 큰 숫자

이중 long형의 경우 64비트 기계어로 번역될 경우에는 운영체제마다 그 크기가 다른데, 윈도우의 경우에는 4바이트, 리눅스의 경우에는 8바이트이다.

실수형[편집 | 원본 편집]

실수형이란 소수점이 붙은 수를 말한다. 컴퓨터에서 실수를 메모리에 저장할 때는 부동 소수점표기 방식을 사용한다.

부동소수점 이란 수학으로 보자면 지수방식으로 실수를 표기하는 것과 같다. 1.123123 x 10^2이런 식으로요, 다만 10^n승이 아니라 2^n으로 표기한다는게 차이점이다.

변수명 float double long double
데이터형 크기 4바이트 8바이트 8바이트 이상

문자형[편집 | 원본 편집]

String 형입니다. string a="김바보"이런 식으로 사용할 수 있습니다. 사실 String은 사용자 정의 타입이기 때문에 더 기능이 있는데, 나중에 알아보도록 합시다.

형변환[편집 | 원본 편집]

형변환(casting)은 다른 데이터형으로 변환하는 것을 말한다.

묵시적 형변환[편집 | 원본 편집]

묵시적 형변환이란 변수를 사용하여 셈을 할 때, 프로그래머가 코드로 이 값을 이 데이터형으로 바꿔라라고 작성하지 않았지만 컴파일러가 이 값을 이 값이란 셈을 하려면 이런 데이터형으로 변환해야 하겠구나라는 판단을 내리고 데이터형을 바꾸는 것을 말한다. 묵시적 형변환은 다음과 같은 우선 순위를 갖는다.

  1. double
  2. float
  3. long
  4. int

왜 다른 데이터형 bool, char, short은 없는가 하면 이들은 다른 데이터형과 셈을 할 때 int형으로 형변환이 된다.

명시적 형변환[편집 | 원본 편집]

각주

  1. 저 숫자다 부분은 생략해서 생각하고 필요할 때 다시 떠올려 봐도 된다.
  2. 쉽게 해석했을 때