C++ 프로그래밍

1. C++ 로의 전환

가. C 기반의 C++ 1

1) C 언어와는 다르게 변수의 선언이 어디서든 가능하다

2) Function Overloading

가) C 컴파일러는 호출하고자 하는 함수를 찾을 때 오로지 함수의 이름 정보만을 가지고 찾기 때문에

정의된 매개 변수의 형태가 달라도 동일한 이름의 함수 정의는 허용하지 않으나 C++ 컴파일러는

함수의 이름뿐 아니라 매개 변수의 정보까지도 참조를 한다. 따라서 C++ 컴파일러는 이름이 같고

매개 변수의 타입 혹은 개수가 다른 함수들의 정의를 허용한다.

나) C++ 은 함수의 이름이 같아도 매개 변수의 타입 및 개수가 다르면 문제되지 않으며, 이를 가리켜

"함수가 오버로딩되었다" 라고 표현한다.

다) 리턴 타입만 달라서는 함수가 오버로딩되지 않는다.

3) Default 매개 변수

가) int function(int a=0) 으로 정의할 때 "function()" == "function(0)"

나) 함수의 선언이 함수의 정의 이전에 존재하는 경우 디폴트 매개 변수는 선언 부분에 놓아져야 한다.

다) int function(int a=10), int function(void) 으로 함수 오버로딩을 할 때 function() 함수를

호출하면 두 함수 모두 호출 가능하므로 에러를 일으킨다. 그러므로 이러한 형식의 함수 정의는

반드시 지양해야 한다.

4) in-line 함수

가) 함수를 매크로로 정의하면 전처리기에 의해서 함수 호출 문장이 함수의 몸체 부분으로 대치되는데

이는 함수 호출 과정(스택 메모리 공간의 할당도 요구하며 시간도 많이 요구)이 사라지므로 성능상

이점이 있으나 함수의 구현이 까다롭고 디버깅하기 어려우며 구현하고자 하는 함수의 크기가 크다면

프로그램의 크기가 커지게 된다는 단점이 있다. ex) #define SQUARE(x)       ((x)*(x))

ex) 와 같이 함수 호출 문장이 함수의 몸체 부분으로 완전히 대치되 버리는 현상을 가리켜

“함수가 inline화 되었다”라고 표현한다.

나) 위의 ex) 를 C++ 스타일로 하면 inline int SQUARE(int x) { return x*x; } 이 된다. 키워드 inline 은

함수 SQUARE 를 inline 화 하라는 의미이다. C++ 에서는 성능 향상을 목적으로 함수를 inline 화하기 위해

매크로를 사용할 필요가 없다. 다만 inline 이라는 키워드만 붙이면 된다.

다) 매크로를 이용한 함수의 in-line 화는 전처리기에 의해서 처리되지만, 키워드 inline 을 이용한 함수의

in-line 화는 컴파일러에 의해서 처리된다. 또한 컴파일러에 따라서는 inline 선언이 오히려 성능 향상에

해가 된다고 판단될 경우, 그냥 무시하기도 한다.

5) namespace

가) namespace (이름공간) 란 이름을 지니는 공간이란 뜻이다. 말 그대로 특정 영역(공간)에 이름을

붙여주기 위한 문법적 요소이다. 이는 프로그램이 대형화되어 가면서 등장하기 시작한 문제로 이름의

충돌이 그 문제이다. namespace 가 다르면 같은 이름의 변수나 함수의 선언이 허용된다.

나) namespace 내에 선언되어 있는 변수나 함수의 접근은 :: 연산자 (범위 지정 연산자 : scope resolution

operator) 라 하며 namespace 의 범위를 지정할 때 사용하는 것이다.

다) using 키워드로 namespace 안에 존재하는 함수를 범위 지정 연산 없이 호출 가능하며 namespace 범위를

크게 잡으면 프로그래밍하기에는 조금 편리하지만 이름 충돌이 발생할 확률은 상대적으로 높아지므로

필요한 부분만 using 선언을 해야하는 것이 올바르다.

라) 지역 변수는 전역 변수의 이름을 가리게 된다. 하지만 :: 연산자를 사용함으로 지역내에서도

전역 변수에 접근이 가능하다. ex) ::전역변수명

범위 지정 연산자의 왼편에는 접근하고자 하는 이름공간, 그리고 오른편에는 접근하고자 하는 변수 혹은

함수의 이름이 오게 되어 있다. 그런데 ex) 와 같은 범위 지정 연산자의 경우에는 접근하고자 하는

이름 공간이 존재하지 않는다. 이것으로 전역 변수로 선언되어 있는 변수에 접근하는 것이 가능하다.

나. C 기반의 C++ 2

1) C 에는 존재하지 않았던 bool 이라는 자료형이 있다. bool 의 값으로 true 와 false 는 각각 1과 0으로

되어 있는 상수라는 느낌을 강하게 받는다. 물론 그렇게 이해해도 큰 지장은 없으나 true 와 false 는

그냥 bool 형 데이터로서 인정을 해 줘야 한다. int 형 상수 1 과 0 이 아니라는 것이다. 다만 int 형으로

변환시 1 과 0 이 되는 것 뿐이다. 또 한가지 더 알아 둘 것은 최근 표준에서는 bool, true, false 가

C 언어의 표준에도 포함되어 있다.

2) Reference

가) 이름을 지니고 있는 대상에게 지어주는 별명을 가리켜 레퍼런스라 한다. ex) int & ref = val;

레퍼런스가 가지고 하는 연산은 레퍼런스가 참조하는 변수의 이름을 갖고 하는 연산과 같은 효과를 지닌다

나) 변수란? 메모리 공간에 할당된 이름을 의미하는 것으로 이 이름을 통하여 메모리 공간에 접근을

하게 된다. 레퍼런스 선언이란 이름이 존재하는 메모리 공간에 하나의 이름을 더 부여하는 행위이며,

레퍼런스와 변수는 생성되는 방법에 있어서만 차이를 보일 뿐 일단 만들어지고 나면 완전히 같은 것이다.

다) 레퍼런스의 선언에 있어서 레퍼런스는 초기화되지 않거나 상수가 올 수 없다.

라) 레퍼런스의 선언 앞에 const 키워드를 붙이므로 레퍼런스를 통한 데이터의 조작을 허용하지 않는다.

이는 레퍼런스의 특성으로 인해 원본 데이터가 변경되는 문제 발생을 없애 줄 수 있다.

마) 레퍼런스를 리턴할 때는 주의해야 할 사항이 한가지 있는데 지역 변수는 레퍼런스로 리턴할 수 없다

3) new & delete

가) C++에서 메모리를 동적으로 할당 및 소멸하기 new 와 delete 키워드가 있다.

나) int * val = new int; ===> delete val; 일반 변수 할당 및 소멸

int * arr = new int[size]; ===> delete []arr; 배열 할당 및 소멸

할당된 메모리 공간일 경우 2차원 배열이건, 3차원 배열이건 delete []배열명; 을 사용한다.

다) new 연산자에 의한 메모리 할당이 실패했을 경우, bad_alloc 예외를 발생시키는 형태로 C++ 표준은

변경되었으나 메모리 할당 실패 시 NULL 포인터가 리턴된다고 이해하면 된다.

2. 객체지향의 도입

가. class 의 기본

1) 구조체와 클래스

가) 구조체의 이점은 관련 있는 데이터를 하나로 묶으면 관리하기에도, 프로그래밍 하기에도 편리하다

대부분의 프로그램은 필요로 하는 데이터들이 부류를 형성한다. 따라서 부류를 형성하는 데이터들을

하나의 자료형으로 정의해서, 관리 및 프로그램 구현에 도움을 주겠다는 의도로 구조체가 등장했다.

나) C 언어와 달리 C++ 의 메커니즘에는 사용자 정의 자료형과 기본 자료형을 동일시하자는

기본 철학이 있다.

다) 프로그램 = 데이터 + 데이터를 조작하는 루틴(함수)

라) 잘 구성된 프로그램들은 데이터들만을 가지고 부류를 형성하는 것이 아니라, 데이터를 조작하는

루틴, 즉 함수와 더불어 부류를 형성하기 마련이다.

마) C++ 에서의 구조체는 클래스라는 넓은 개념의 일부로 존재한다. C++ 에서의 구조체는 C 언어에서의

구조체와 특징에 있어서 거리가 조금 멀다. 구조체도 클래스라는 범주에 속해 있으면서,

다른 클래스들과는 조금 다른 특징을 지닐 뿐이다. 구조체는 멤버 변수, 함수가 public 이라는 것이다.

바) class = attribute (속성) + method (방법) 여기서 attribute 라는 것은 변수를 의미하는 것이고,

method 라는 것은 함수를 의미하는 것이다. 보통은 attribute 를 가리켜 멤버 변수라 하고, method 를

가리켜 멤버 함수라 한다. class = 멤버 변수 + 멤버 함수

2) Object

가) 클래스의 변수는 더 이상 변수라는 표현을 쓰지 않고 ‘객체’라는 표현을 사용한다. 객체란,

세계에 존재하는 주변의 모든 것들을 뜻하는 것으로서 완전한 대상체라는 의미를 지닌다. 즉 프로그램의

세계에서는 데이터와 그 데이터를 적절히 처리하는 함수를 하나로 묶어서 이를 구조체화시키면 이것을

두고 하나의 완전한 대상체로 바라보는 것이다.

3) 클래스와 객체

가) Data Abstraction

현실세계의 사물을 데이터적인 측면과 기능적 측면을 통해서 정의하는 것이며 데이터 추상화에서의

데이터라는 용어는 사물의 데이터적인 측면과 기능적인 측면을 동시에 일컫는 것이다.

나) 클래스

추상화된 데이터(데이터적 측면 + 기능적 측면)를 가지고 자료형을 정의하게 된다. 이 때 사용되는 것이

클래스이다. 이렇게 추상화된 데이터를 가지고 사용자 정의 자료형을 정의하는 것 자체를 가리켜

보통은 ‘클래스화한다’라고 표현한다.

다) 객체

클래스를 이용해서 정의된 자료형의 변수는 객체(object)라는 표현을 쓴다. 그리고 클래스 기반으로

객체를 생성하는 것을 가리켜 “인스턴스화(instantiation)한다 또는 객체화한다”라는 표현을 사용한다.

객체(object)를 가리켜 인스턴스(instance)라고도 표현한다. 사실 이 둘의 단어적 의미에는 아주 미묘한

차이가 있는데, 객체지향 프로그래밍에서는 이 둘을 동일시하는 경향이 강하다.

4) 클래스 멤버의 접근 제어

가) 같은 클래스 내에 존재하는 멤버에 의한 접근을 가리켜 클래스 내부 접근이라하고 이러한 형태가 아닌

그 이외의 모든 접근은 외부 접근에 해당된다.

나) private 으로 멤버가 선언이 되면 클래스의 내부 접근만 허용하겠다는 의미가 되며 public 으로

선언되면 클래스 외부 접근도 허용하겠다는 의미가 된다. 엄밀히 말하면 어디서든지 접근을 허용하겠다

는 의미이다.

5) 멤버 함수의 외부 정의

가) 클래스내 함수 정의를 클래스 외부로 빼냄으로 클래스 내부의 선언을 간결하게 한다.

나) 클래스의 멤버 함수를 내부에 정의한다는 것은 외부에 정의하는 것과 달리 in-line 으로 처리할 것을

요구한다는 의미를 지니고 있다. 요즘 컴파일러는 코드 최적화를 수행하기 때문에 inline 키워드가

있건 없건 큰 의미는 없다.

다) 클래스의 선언은 헤더 파일로 구현을 하고, 클래스 멤버 함수의 정의는 .cpp 파일로 구현을 하면

프로그램을 관리 및 확장하기가 좋아진다.

나. class 의 완성

다. 복사 생성자

라. static 멤버와 const 멤버

3. 객체지향의 전개

가. Inheritance 의 이해

나. 상속과 다형성

다. virtual 의 원리와 다중 상속

4. 객체지향의 완성

가. 연산자 오버로딩

나. string 클래스 디자인

다. 템플릿

라. 예외 처리