
본 글을 개인적 학습을 위한 글입니다. 틀린 내용이 있을 시 마구 지적해주시면 감사합니다.
개요
C++ 에 대한 기초적인 개념을 다루는 글입니다.
문법, 언어의 작동 원리 등을 전공 수준에서 공부하고 필기합니다.
프로그래밍 언어
기본적인 프로그래밍 언어 구분입니다.
- 기계어(Machine Language)
0, 1의 이진수로 구성된 언어. CPU는 본질적으로 기계어만 처리 가능
- 어셈블리어(Assembly -)
기계어의 명령을 ADD, SUB, MOVE 등과 같은 상징적인 니모닉 기호(mnemonic)로 일대일 대응시킨 언어
→ 어셈블러(Assembler) : 어셈블리어 프로그램을 기계어 코드로 변환
- 고급언어(High-level programming Language)
사람이 이해하기 쉽고 복잡한 작업, 자료구조, 알고리즘을 표현하기 위해 고안된 언어
→ 컴파일러 : 고급언어로 작성된 프로그램을 기계어 코드로 변환
C언어의 특성
C++ 알기 위해선 C언어에 대한 기본적인 특성을 이해해야 합니다.
- 중급 언어 : 고급 언어 + 저급 언어(어셈블리어) ⇒ 중급 언어
- 고급 언어 : 인간이 쉽게 이해할 수 있는 문법 구조
- 저급 언어 : 기호화된 상수, 또는 포인터를 이용한 비트 단위의 조작으로 여러 하드웨어 장치들을 제어 가능
- 구조적 언어
- 모듈화(Modulation)
기능들을 서로 분리하여 설계, 코딩, 후에 상호 연관
- 코드와 자료의 분리
필요한 모든 정보와 명령어들을 분리하고 숨길 수 있음
- 함수
함수의 집합, 함수(=Building Block), 한 프로그래머의 코드 블록은 다른 프로그래머의 코드에 영향을 미치지 않도록 독립
- 포인터 개념
- 변수의 현재 내용을 간접적으로 참조
- 메모리 내의 다른 저장내용을 자유롭게, 융통성있게 접근
- C언어로 시스템 프로그램(운영체제, 에디터 등) 작성 가능
- 중대한 오류의 원인이 되기도 함
이 중대한 오류는 포인터가 자바의 Reference의 특성과 다르기에 생길 수 있는 문제이다. 포인터는 실제 메모리 주소를 사용하기 때문에, 잘못 사용한다면 메모리 침범, 누수 등 다양한 문제를 일으킬 수 있다.
A Programmer’s Best Friend
C언어는 특정 분야가 아닌 모든 컴퓨터 프로그래머를 위해 사용 가능하다. 또 이식성(Portability)가 매우 좋은 언어이다. (다양한 운영체제, 다양한 하드웨어에서 사용 가능)
++ 비 프로그래머 언어 예시
- COBOL : 상업 분야
- BASIC : 일반인 대상
- FORTRAN : 수학 분야
C++
: C와 클래스 (C language with classes)
→ C의 효율성 + 객체 지향 개념이라고 볼 수 있습니다.
절차 지향과 객체 지향
객체 지향을 사용하게 된 배경은 소프트웨어 모듈의 재사용과 독립성을 강조하기 위해서로 알려져 있습니다.
- 객체 지향과 절차 지향의 비교
- 절차 지향(Procedural-Oriented)
데이터 구조와 그 데이터를 변화시키는 procedure, function으로 구성
- 객체 지향(Object-Orieted)
객체들이 메시지를 통하여 통신함으로써 원하는 결과를 얻는다. 각 객체는 고유의 속성(Attribute)과 데이터를 처리할 수 있는 메소드(Method)로 구성

객체(Object)
효율적인 정보를 관리하기 위하여, 사람들이 의미를 부여하고, 분류하는 논리적인(개념적인) 단위.
실 세계에 존재하는 하나의 단위에 대한 소프트웨어적 표현, 관련된 변수와 함수의 묶음
구성 : Data(Attribute) + Function(Method)
조금 더 간단하게 표현해보겠습니다. 실 생활에 존재하는 것들, 예를 들어 아이스 아메리카노와 관련한 프로그램을 개발한다고 생각했을 때, 언어 내에 존재하는 Primitives로는 이에 대한 데이터 표현에 제한을 가질 수 있습니다. 물론 C언어에 존재하는 Structure(구조체)를 이용하면 이를 어느 정도 해소할 수 있지만, 이와 관련한 문제를 해결하기 위해 전역 함수(Global Method)를 사용해야 하기에 그다지 좋은 패턴이라고 할 수 없을 것입니다. 우리는 이러한 경우들에 대해 프로그래밍적으로 잘 대처하기 위해 객체 개념을 잘 이해하고 사용해야 합니다.
객체 지향 프로그래밍의 특징
- 캡슐화(Encapsulation)
- 다형성(Polymorphism) + Virtual Functions
- 상속(Inheritance)
C++의 표준화(Standardization)
표준의 중요성
모든 플랫폼, 모든 표준 C++ 컴파일러에 의해 컴파일, 동일한 실행 결과 보장, 운영체제와 컴파일러의 종류에 관계없는 높은 호환성을 가져야 합니다.
C++의 주요한 설계 목적
- C언어와의 호환성
- 소스 레벨 호환성(기존에 작성된 C 프로그램을 사용 가능)
- 링크 레벨 호환성(C obj파일과 라이브러리를 C++에서 링크 가능)
- 객체 지향 개념 도입
- 캡슐화, 상속, 다형성
- 소프트웨어의 재사용을 통해 생산성 향상
- 복잡하고 큰 규모의 소프트웨어 작성, 관리, 유지보수 용이
- 제네릭 프로그래밍(Generic Programming)
- 코드의 재사용성을 극대화시키는 새로운 프로그래밍 패러다임
→ E.g. Integer에서만 돌아가는 프로그램이 Float, Char에서도 돌아갈 수 있도록 하는 프로그래밍
- 구조적 예외처리
- 실행 시간 오류의 가능성을 줄임, 디버깅 편리
C언어와의 호환성 위에 추가된 기능
- 인라인 함수(Inline Function)
- 함수 호출대신 함수 코드의 확장 삽입 (Macro와는 차이가 있음)
- 함수 중복(Function Overloading)
- 매개 변수가 다른 동일한 이름의 함수 집합을 선언 가능
- 디폴트 매개변수(Default Parameter)
- 매개 변수에 디폴트 값이 전달되도록 함수 선언
- 참조와 참조 변수(Reference and Reference Variable)
- 하나의 변수에 별명을 사용하는 참조 변수 도입
- 참조에 의한 호출(Call-By-Reference)
- new, delete 연산자
- Dynamic Memory Allocate, Deallocate
- 연산자 재정의(Operator Overloading)
- 제네릭 함수와 클래스
- 데이터 타입에 의존하지 않고 일반화시킨 함수나 클래스 작성 가능
C++에 객체 지향을 도입한 목적
- 소프트웨어 생산성 향상
- 소프트웨어의 생명 주기 연장의 목적
- 기작성된 코드의 재사용 및 손쉬운 유지 보수
- 클래스 상속 및 객체 재사용으로 해결
- 실세계에 대한 쉬운 모델링
- 과거의 소프트웨어 → 수학 계산이나 통계 처리에 편리한 절차 지향 언어가 적합
- 현대의 소프트웨어 → 물체 혹은 객체의 상호작용에 대한 묘사가 필요, 실세계는 객체로 구성된 세계
C++와 제네릭 프로그래밍
- 제네릭 함수와 제네릭 클래스
- 제네릭 함수
동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화시킨 함수
- 제네릭 클래스
동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화시킨 클래스
C++의 구조적 예외 처리(Exception Handling)
→ 추후에 더 자세히 다룰 것임.
C++가 갖는 문제점
C++ 는 C언어와의 호환성을 추구하여 갖는 장점과 단점이 명확하게 구분됩니다.
- 장점 : 기존에 개발된 C 프로그램 코드 활용 가능
- 단점 : 캡슐화의 원칙이 무너짐
- C++에서 전역변수와 전역함수를 사용할 수 밖에 없음
- 부작용(Side-Effect) 발생 염려
C++ 프로그램 개발 과정

- 빌드(Build) = 컴파일(Compile) + 링킹(Linking)
- 컴파일(Complie) : 목적 파일(.obj, .o)을 제작
→ 목적 파일을 여러 개 한 데 모아 압축시킨 것을 라이브러리(.lib ~= .dll)라고 한다.
- 링킹(Linking) : 목적 파일을 합쳐 실행 파일(.exe)을 만드는 과정(목적 파일은 바로 실행 불가)
프로그램 실행과 디버깅
-
실행 파일은 독립적으로 바로 실행 가능
-
실행 중에 발생하는 오류
→ 원하는 결과가 나오지 않거나 실행 중에 프로그램의 비정상 종료
-
컴파일 에러(Compile Error) : 문법 오류가 있을 때 발생한다.
-
링킹 에러(Linking Error) : 컴파일 후에 소스파일에 없는 함수가 있거나, 링킹과 관련된 문제가 생기면 발생한다.
-
디버깅(Debugging)
: 실행 중에 발생한 오류를 찾는 과정
-
디버거(Debugger)
: 디버깅을 도와주는 프로그램, 컴파일러를 만드는 회사에서 함께 배포
-
소스 레벨 디버깅(Source-level-Debugging)
: C++의 소스 코드를 한 라인씩 실행하고 변수 값의 변화를 보면서 오류 발견
C++ 표준 라이브러리
- C 라이브러리 : 기존 C 표준 라이브러리를 수용
- C++ 입출력 라이브러리 : 콘솔 및 파일 입출력을 위한 라이브러리
- C++ STL : 제네릭 프로그래밍을 지원하기 위한 템플릿 라이브러리
printf() 를 잘 사용하지 않는 이유
int a = 10;
printf("%f", a);
위의 경우이면 실행이 되지 않는 것이 정상적일 것이다.
하지만, 값이 0.00000.. 으로 출력되어 문제가 발생한다.
이는 scanf()도 마찬가지이다.
⇒ 즉, 에러가 발생해도 그냥 넘어간다.
C++에서 이에 대체제로 std::cout, std::cin 이 사용된다.
int a = 10;
std::cout << a;
조금 더 자세한 설명을 해보자면, 보통 함수와 변수를 구분할 때 괄호의 여부로 이를 판단한다.
cout과 cin에는 이 괄호가 존재하지 않아, 변수임을 우리가 알 수 있다.
즉, cout과 cin은 변수(객체)이고, <<가 연산자로써 사용되는 것이다.
- 스트림 삽입 연산자 (<<)
- 스트립 추출 연산자 (>>)
Namespace
이름(Identifier) 충돌이 발생하는 경우(여러 명이 하나의 프로젝트 개발, 오픈 소스의 사용 등)
→ 이를 해결하는데에 많은 시간과 노력이 필요하다.
C++에서는 이를 Namespace 개념을 통해 해결했다.
A::B
Namespace를 생략하는 방법
using namespace A;
using namespace std;
using namespace std::cout;
위와 같이 using 지시어를 사용해서 생략할 수 있다.
std::
ANSI C++ 표준에서 정의한 namespace 중 하나
오늘은 프로그래밍 언어에 대한 기본적인 정보와 C, C++ 의 특성에 대해 간략하게 공부해보았습니다. 다음에는 C++의 기본적인 문법에 대해 다룹니다.
이상입니다.
참고 자료