본문 바로가기
UNSEEN

UNSEEN 대비 2. C++ 언어의 특징

by 니키티스 2024. 1. 25.

- 해당 글은 UNSEEN 2기 코딩 테스트를 대비하여 정리 목적으로 적은 글입니다. 잘못된 부분이 있다면 지적해주시면 감사하겠습니다.

1. 설계 주요 목표

  • C언어와의 호환성: 기존 C언어 코드를 그대로 사용할 수 있도록 C언어의 문법을 그대로 가져온다.
  • 객체지향: 소프트웨어를 재사용하여 생산성을 높이기 위해 객제지향 개념을 도입
  • 타입 체크: 타입 체크를 엄격히 하여 실행 시간 오류의 가능성을 줄이고 디버깅을 도움
  • 효율성 저하 최소화: 성능에 영향을 주지 않는 선에서 기능을 추가한다. 예를 들어 함수의 인라인을 통해 함수 호출로 인한 시간을 최소화한다.

2. C++의 특징

C에서 C++로 오면서 많은 특징이 추가되었다. 가장 대표적인 것은 객체지향 프로그래밍이 가능해진 점이고, 그 이외에도 bool 자료형, 참조자 추가, 메서드 오버로딩, 연산자 오버로딩이 생기면서 C언어와는 완전히 새로운 언어가 나타났다고 볼 수 있다.

객체지향적 특징의 추가

C++에서는 코드를 재사용하여 소프트웨어 생산성을 올리기 위해 객체지향적인 특징을 추가하였다. 상속, 가상 함수, 접근 제한자, 다형성 등이 이를 위한 기능이다.

새로운 자료형의 추가

C++98에서 bool 자료형이 추가되었다. 여타 언어처럼 true, false로 조건문을 검사할 수 있다.

// 이제 다음과 같이 작성할 수 있다.
while (true)
{
        ...
}

참조(reference)자가 추가되었다. 참조형 변수는 일종의 포인터이지만, 포인터를 더 안전하게 사용할 수 있다. & 연산자로 사용할 수 있으며, 한 번 참조한 변수는 다시 변경할 수 없다.

int number = 100;
int& reference = number; // number에 대한 별칭으로 사용된다.

C언어는 일반적으로 변수의 값만을 전달할 수 있다 하여 ‘값에 의한 호출(Call by value)’이라 칭한다. 포인터도 메모리 상의 주소를 가리키는 일종의 값이라 보기 때문이다.

반면, C++에서는 참조형 변수가 생기면서 ‘참조에 의한 호출(Call by reference)’을 사용할 수 있다. Java와 유사하게, 함수 호출시 참조를 전달할 수 있는 것이다.

#include <iostream>

int callbyref(int& k)
{
    k++; // k의 참조에 대해 값을 변경
}

int main()
{
    int a = 10;
    std::cout << a << std::endl; // 10 출력
    callbyref(a); // a의 참조를 전달하면서, a = 11이 된다.
    std::cout << a << std::endl; // 11 출력
}

용도에 따라 lvalue 참조, rvalue 참조가 별도로 존재한다.

오버로딩

메서드 오버로딩(method overloading)이 추가되어 중복된 이름의 함수를 선언할 수 있다. 매개 변수의 개수나 형식에 따라 적절한 함수를 호출한다.

연산자 오버로딩(operator overloading)을 지원하여 이제 프로그래머가 연산자를 재정의할 수 있다. 함수 오버로딩과 유사한데, 예를 들어 (int) + (int) 같은 연산이 아니라 구조체 Vector에 대해 (Vector) + (Vector) 등의 연산을 정의할 수 있다. 연산자 오버로딩은 Java에서는 불가능하다.

C++에서 이것이 가능한 이유는 연산자를 메서드로 보기 때문이다.

오버로딩 가능한 연산자: + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= <=>(since C++20) && || ++ -- , ->* -> ( ) [ ](operator overloading - cppreference.com)

템플릿과 제네릭 프로그래밍

제네릭 프로그래밍(generic programming)은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.

C++에서는 템플릿을 사용하면 자료형마다 코드를 중복해서 짜지 않아도 된다.

template <typename T>
T Add(T a, T b)
{
    return a + b;
}

int main()
{
    int intValue = Add<int>(1, 2); // 1 + 2
    float floatValue = Add<float>(3.14f, 2.1828f);
}

다양한 라이브러리

C++에는 STL(Standard Template Library, 표준 템플릿 라이브러리)와 같이 다양한 라이브러리를 지원하고 있어 C언어와 달리 모든 코드를 짤 필요가 없다. 따라서 C++ 개발자는 라이브러리를 활용하여 빠르게 소프트웨어를 생산할 수 있다.

STL에는 vector, map, set, queue, stack, list 등 편리한 컨테이너가 많이 존재한다.

여기 적힌 항목 이외에도 C++ 11/14/17/20 등의 표준에서 꾸준히 새로운 기능이 발표되고 있다.

메모리 관리

Java, C# 등의 다른 언어와 달리 C++는 C언어와 마찬가지로 포인터를 통해 개발자가 직접 메모리를 할당하고 해제할 수 있다. 효율적이고 빠른 어플리케이션을 작성할 수 있다는 점에서 장점이지만 메모리 관리를 잘못하면 메모리 누수 등이 생겨 위험성도 존재한다.

3. 객체지향 프로그래밍 지원

객체지향 프로그래밍에 실세계가 객체로 이루어져 있으며 모든 현상과 사건이 객체의 상호작용에 의해 발생한다 본다. 객체지향 프로그래밍은 실세계에 가깝게 표현하기 위해 여러 객체들을 통해 전체 프로그램을 구축한다.

C++에서는 객체지향 프로그래밍을 지원하면서 객체의 생성과 상속 등의 문법을 사용할 수 있다.

객체

객체지향 프로그래밍에서는 클래스를 만들고 클래스로부터 객체를 찍어낸다.

이를 비유하기 위해 붕어빵 틀 예시를 많이 든다. 붕어빵 틀이 있으면, 그 안에 반죽을 부어 붕어빵을 찍어낼 수 있다. 붕어빵 틀이 ‘클래스’라는 개념이고 붕어빵이 ‘객체’이라고 생각할 수 있다.

클래스가 실재하는 무언가(객체)를 만드는 이라면, 객체는 설계도로부터 만들어진 실물인 셈이다.

C++에서 클래스는 아래와 같이 class 키워드로 작성한다.

class Vector
{
public:
    Vector() : mX(0), mY(0)
    {
    }
private:
    int mX;
    int mY;
}

C++에서는 new, delete로 힙(Heap) 공간에 객체를 생성할 수 있는데, 스택 공간에 지역 변수로 객체를 생성할 수도 있다. 이 점이 C#, Java와의 가장 큰 차이점이다.

C++에는 객체지향 프로그래밍의 4가지 특징인 추상화, 상속, 다형성, 캡슐화가 모두 존재한다.

객체지향 프로그래밍에 관한 내용은 이전 글에 작성해놓았으니 궁금한 분들을 읽어보면 좋을 것 같다.

참고

[C++] C++ 시작하기 - 특징, 객체 지향, 컴파일과 링킹 - HERSTORY (4z7l.github.io)

참조 (C++) | Microsoft Learn

C++ 언어 소개: 기본 개념과 특징, 커리큘럼(공부 순서) (tistory.com)

제네릭 프로그래밍 - 위키백과, 우리 모두의 백과사전 (wikipedia.org)

댓글