The C++ Programming Language - Basic of C++

an_yan_yang·2025년 2월 3일

본 글을 개인적 학습을 위한 글입니다. 틀린 내용이 있을 시 마구 지적해주시면 감사합니다.

개요

  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++와 제네릭 프로그래밍

  • 제네릭 함수와 제네릭 클래스
    • 제네릭 함수
        동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화시킨 함수
    • 제네릭 클래스
        동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화시킨 클래스

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 // A에 속해있는 B라는 의미 (A를 namespace라 한다.)

Namespace를 생략하는 방법

using namespace A;
using namespace std; // std에 선언된 모든 identifier에 std:: 생략
using namespace std::cout; // cout에 대해서만 std:: 생략

위와 같이 using 지시어를 사용해서 생략할 수 있다.


std::

ANSI C++ 표준에서 정의한 namespace 중 하나



오늘은 프로그래밍 언어에 대한 기본적인 정보와 C, C++ 의 특성에 대해 간략하게 공부해보았습니다. 다음에는 C++의 기본적인 문법에 대해 다룹니다.

이상입니다.


참고 자료

profile
개발자가 되고 싶은 공대생

0개의 댓글