맨위로가기

C++

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

C++는 1979년 비야네 스트롭스트룹이 C 언어에 객체 지향 프로그래밍 기능을 추가하여 개발한 프로그래밍 언어이다. 초기에는 "C with Classes"로 시작하여 1983년 "C++"로 이름이 변경되었으며, 1985년 첫 번째 공식 표준이 없는 상태에서 C++ 프로그래밍 언어 서적이 절대적인 참조 문헌이 되었다. C++는 ISO의 JTC1/SC22/WG21 작업반에 의해 표준화되었으며, 1998년 C++98을 시작으로 C++03, C++11, C++14, C++17, C++20, C++23 등 지속적으로 개정 및 발전해왔다. C++는 객체 지향 프로그래밍의 핵심 특징인 캡슐화, 상속, 다형성, 템플릿, 예외 처리, 람다 표현식 등을 지원하며, C 언어의 하위 집합으로 시작되었지만, C99의 도입 이후 C와 완벽하게 호환되지는 않는다. C++ 표준 라이브러리는 다양한 자료구조, 알고리즘, 입출력 기능을 제공하며, C++ 코어 가이드라인은 '모던 C++'을 작성하기 위한 모범 사례를 제시한다.

더 읽어볼만한 페이지

  • 1983년 개발된 프로그래밍 언어 - Occam
    Occam은 1980년대에 개발된 동시성 프로그래밍 언어이며, 들여쓰기와 채널을 통한 통신을 특징으로 하며, `SEQ`, `PAR`, `ALT` 등의 명령어를 사용하고 여러 버전으로 발전했다.
  • 1983년 개발된 프로그래밍 언어 - GW 베이직
    GW-BASIC은 1980년대 마이크로소프트에서 개발한 BASIC 프로그래밍 언어의 인터프리터 버전이며, IBM PC 하드웨어 기능을 추가하여 사운드와 그래픽 기능을 활용한다.
  • 알골 프로그래밍 언어 계열 - 알골 (프로그래밍 언어)
    알골은 1950년대 후반 유럽 학자들이 개발한 명령형 프로그래밍 언어로서, BNF 표기법으로 문법이 기술되고 구조화된 프로그래밍 형태를 갖추어 이후 여러 언어에 영향을 주었으며, 특히 알골 60은 재귀 호출 지원으로 소프트웨어 모듈화와 컴퓨터 범용화에 기여하고 프로그래밍 개념 표준 용어 제공에 중요한 역할을 했다.
  • 알골 프로그래밍 언어 계열 - 알골 60
    알골 60은 1960년에 발표된 프로그래밍 언어이며, 바쿠스-나우르 표기법을 사용하여 재귀를 포함하고, 이후 많은 언어에 영향을 미쳤지만 입출력 기능 부재로 이식성에 문제가 있었다.
  • C++ 프로그래밍 언어 계열 - C++/CLI
    C++/CLI는 .NET 환경에서 관리 코드와 네이티브 코드의 혼합 사용을 위해 C++ 언어를 확장한 것으로, .NET 객체 생성, 핸들, 추적 참조 등의 구문을 제공하며 C# 등 다른 .NET 언어와의 상호 운용성을 지원한다.
  • C++ 프로그래밍 언어 계열 - C++/CX
    C++/CX는 Windows 런타임 프로그래밍을 위해 C++ 언어를 확장한 것으로, WinRT 객체 생성에 `ref new`를 사용하고, 참조 포인터(`^`)를 활용하며, 다른 언어와의 코드 공유를 위해 메타데이터를 통해 클래스와 멤버를 노출한다.
C++ - [IT 관련 정보]에 관한 문서
기본 정보
C++ 표준 위원회에서 승인한 로고
이름C++
설명범용 프로그래밍 언어
설계자비야네 스트롭스트룹
개발자ISO/IEC JTC 1 (합동 기술 위원회 1) / SC 22 (분과 위원회 22) / WG 21 (실무 그룹 21)
최신 버전C++23 (ISO/IEC 14882:2024)
최신 미리보기 버전C++26
패러다임다중 패러다임: 절차적 프로그래밍, 명령형 프로그래밍, 함수형 프로그래밍, 객체 지향 프로그래밍, 제네릭 프로그래밍, 모듈식
계열C
형 체계정적, 강한, 명목적, 부분적으로 추론됨
운영 체제크로스 플랫폼
파일 확장자.C, .cc, .cpp, .cxx, .c++, .h, .H, .hh, .hpp, .hxx, .h++, .cppm, .ixx
구현체GCC, LLVM Clang, Microsoft Visual C++, Embarcadero C++Builder, Intel C++ Compiler, IBM XL C++, EDG
위키책C++ 프로그래밍
영향을 받은 언어에이다
알골 68
BCPL
C
CLU
F 샵
ML
메사
Modula-2
시뮬라
스몰토크
영향을 준 언어에이다 95
C#
C99
카본
채플
클로저
D
자바
JS++
루아

Objective-C++

PHP
파이썬
러스트
Seed7
기타 정보
웹사이트비야네 스트롭스트룹의 홈페이지

2. 역사

1979년, 덴마크의 컴퓨터 과학자 비야네 스트롭스트룹은 박사 과정 중 프로그래밍 경험을 바탕으로 C 언어를 확장한 "C with Classes" 개발을 시작했다.[149][28] 그는 시뮬라처럼 대규모 소프트웨어 개발에 유용한 기능을 가지면서도 BCPL처럼 빠른 언어를 만들고자 했다.[29] 당시 AT&T 벨 연구소에서 일하며 유닉스 커널 분석 문제를 해결하기 위해 C를 기반으로 클래스, 파생 클래스, 강력한 타이핑, 인라이닝, 기본 인수 등의 기능을 추가했다.[150][30]

Bjarne Stroustrup(비야르네 스트롭스트룹), C++의 창시자, AT&T 뉴저지 사무실, 2000년경


1983년, 언어 이름은 C의 증가 연산자(++)에서 아이디어를 얻어 "C++"로 변경되었다.[30] 이때 가상 함수, 함수 및 연산자 오버로딩, 참조, 상수(`const`), 타입 검사가 강화된 메모리 관리(`new`/`delete`), BCPL 스타일의 한 줄 주석(`//`) 등 중요한 기능들이 추가되었다.[30] 스트롭스트룹은 C++를 위한 독립 컴파일러인 Cfront도 개발했다.

1985년에는 C++의 첫 번째 상용 구현체가 출시되었고,[149][28] 같은 해 『C++ 프로그래밍 언어』 제1판이 출간되어 당시 공식 표준이 없던 C++의 사실상 표준 역할을 했다.[151][31] 1989년에는 C++ 2.0이 발표되어 다중 상속, 추상 클래스, 정적 멤버 함수, 상수 멤버 함수, 보호(`protected`) 멤버 등의 기능이 추가되었다.[32] 1990년에는 표준화의 기초가 된 『주석이 달린 C++ 참조 설명서』(The Annotated C++ Reference Manual, ARM)가 출판되었다.[107] 이후 템플릿, 예외 처리, 네임스페이스, 새로운 캐스트, 부울형 등이 언어에 추가되었다.

C++ 언어는 이후 표준화 과정을 거쳐 1998년에 첫 국제 표준인 C++98이 제정되었고,[143] 2003년에 이를 일부 수정한 C++03이 발표되었다.[144] 이후 C++11(2011년), C++14(2014년), C++17(2017년), C++20(2020년) 등 여러 차례 개정을 통해 언어와 표준 라이브러리가 지속적으로 발전하고 있다.[145][146][147][148]

2. 1. 국제 표준

C++는 ISO의 JTC1/SC22/WG21 작업반에 의해 표준화된다. 지금까지 C++ 표준은 여러 차례 개정되었으며, 현재 다음 개정판인 C++26 작업이 진행 중이다.

1996년 스톡홀름에서 열린 C++ 표준 위원회 회의 장면


1998년, ISO 작업반은 C++를 처음으로 ''ISO/IEC 14882:1998''로 표준화했으며, 이는 비공식적으로 ''C++98''로 알려져 있다.[143][41][109] 이후 2003년에는 C++98에서 발견된 문제점을 수정한 ''ISO/IEC 14882:2003''(C++03)이 발표되었다.[144][42][110] 2003년 12월에 제정된 한국산업규격 KS X 3014:2003은 ISO/IEC 14882:2003의 한국어 번역본이다.

다음 주요 개정판은 C++11(ISO/IEC 14882:2011)로, 핵심 언어와 표준 라이브러리 모두에 많은 새로운 기능이 추가되었다.[145][43][112] 이후 C++14(ISO/IEC 14882:2014),[146][44][113] C++17(ISO/IEC 14882:2017),[147][45][114] C++20(ISO/IEC 14882:2020)[148][46][115]이 차례로 발표되며 언어와 라이브러리가 지속적으로 개선되었다. 가장 최근 표준은 C++23(ISO/IEC 14882:2024)이다.[47]

C++ 표준
연도ISO/IEC 표준비공식 명칭
1998ISO/IEC 14882:1998[143][41][109]C++98
2003ISO/IEC 14882:2003[144][42][110]C++03
2011ISO/IEC 14882:2011[145][43][112]C++11, C++0x
2014ISO/IEC 14882:2014[146][44][113]C++14, C++1y
2017ISO/IEC 14882:2017[147][45][114]C++17, C++1z
2020ISO/IEC 14882:2020[148][46][115]C++20, C++2a
2024ISO/IEC 14882:2024[47]C++23, C++2b
작업 중C++26, C++2c



표준화 과정의 일환으로 ISO는 기술 보고서(TR) 및 기술 명세서(TS)도 발표한다. 여기에는 표준에 포함되기 전의 실험적인 기능이나 특정 분야를 위한 확장 기능이 포함된다. 예를 들어, TR1(ISO/IEC TR 19768:2007)[53][111]은 C++11에 포함된 여러 라이브러리 확장의 기반이 되었고, 파일 시스템 라이브러리(ISO/IEC TS 18822:2015)[56], 병렬 알고리즘(ISO/IEC TS 19570:2015)[57], 개념(ISO/IEC TS 19217:2015)[60], 코루틴(ISO/IEC TS 22277:2017)[64], 모듈(ISO/IEC TS 21544:2018)[66] 등 다양한 TS가 이후 표준에 통합되었다.

=== 표준 준수 ===

C++ 언어의 복잡성 때문에 표준을 완벽하게 준수하는 컴파일러를 개발하는 것은 어려운 과제이다. 과거에는 컴파일러마다 표준 준수 수준에 차이가 있었으며, 특히 템플릿 관련 기능에서 구현 차이가 두드러졌다. 예를 들어, C++98 표준에 포함되었던 `export` 키워드는 템플릿의 선언과 구현을 분리하기 위한 기능이었으나, 구현의 어려움 때문에 소수의 컴파일러만 지원했고 결국 C++11에서 제거되었다.[134][135]

또한, C++ 표준은 이름 장식이나 예외 처리 메커니즘 등 일부 구현 관련 세부 사항을 컴파일러 제작자의 재량에 맡기고 있다. 이로 인해 서로 다른 컴파일러로 빌드된 오브젝트 파일 간의 호환성 문제가 발생할 수 있다. 이러한 문제를 해결하기 위해 특정 플랫폼이나 운영체제에서 컴파일러 간 호환성을 보장하는 ABI(Application Binary Interface) 규격[136]이 별도로 정의되기도 한다.

최근 주요 C++ 컴파일러(GCC, Clang, Visual C++, Intel C++ Compiler)들은 C++11C++14 표준을 거의 완벽하게 지원하며, C++17, C++20, C++23 기능들도 빠르게 구현하고 있다.[137][138] 하지만 최신 표준 기능에 대한 지원 수준은 컴파일러마다 여전히 차이가 있을 수 있다.

3. 특징

C++는 C 언어를 기반으로 객체 지향 프로그래밍과 일반화 프로그래밍 등의 기능을 추가하여 개발된 다중 패러다임 프로그래밍 언어이다.[152] C 언어의 절차적 프로그래밍 방식 또한 그대로 지원하므로, C++은 다양한 프로그래밍 스타일을 포괄적으로 지원한다.[29]

초기 C++는 C 코드로 변환 후 컴파일하는 트랜스레이터 형태로 개발되어 C 언어와 높은 호환성을 가졌다. 이후 C 언어 표준에 `const` 키워드 등 C++ 기능이 일부 도입되기도 했으나, C99 표준 등장 이후 C++과 C 언어 사이의 엄격한 호환성은 일부 약화되어 C++이 C의 완전한 상위 집합(superset)은 아니게 되었다. 그러나 C++ 표준은 지속적으로 발전하여 C와의 호환성을 고려하고 있다.

C++는 다음과 같은 다양한 특징을 가지고 있어 언어 표준 규격이 상당히 복잡하다.


  • 객체 지향 프로그래밍: 클래스를 통해 캡슐화, 상속, 다형성 등 객체 지향의 핵심 개념을 지원하며, 특히 다중 상속 기능이 특징적이다.
  • 템플릿: 일반화 프로그래밍을 가능하게 하여, 특정 타입에 의존하지 않는 유연하고 재사용 가능한 코드를 작성할 수 있게 한다. 템플릿 메타 프로그래밍과 같은 고급 기법도 지원한다.
  • 연산자 오버로딩: 대부분의 기본 연산자 기능을 사용자 정의 타입에 맞게 재정의하여, 사용자 정의 타입을 내장 타입처럼 자연스럽게 사용할 수 있게 한다.
  • 예외 처리: 프로그램 실행 중 발생하는 오류나 예외적인 상황을 `try`, `catch`, `throw` 키워드를 사용하여 구조적으로 처리하는 방법을 제공한다.
  • 람다 표현식: 익명 함수를 간결하게 정의하고 사용할 수 있는 기능을 제공하여 함수형 프로그래밍 스타일의 구현을 돕는다.
  • 실행시 형식 식별(RTTI): 프로그램 실행 중에 `typeid` 연산자나 `dynamic_cast` 등을 통해 객체의 실제 타입을 확인하는 기능을 제공한다.


이처럼 C++는 C 언어의 효율성과 하드웨어 접근 능력[69]을 유지하면서 강력한 추상화 메커니즘을 제공하는 것을 목표로 한다.[16] 그러나 다양한 기능과 유연성으로 인해 언어가 매우 복잡해졌다는 평가도 받으며, 이러한 복잡성 때문에 C++의 특정 측면을 단순화하거나 다른 설계를 채택한 자바, C#, D 언어와 같은 새로운 언어들이 등장하기도 했다.

C++의 설계와 발전 과정에는 다음과 같은 핵심 원칙들이 반영되었다.[29]

  • 실제 문제 해결에 유용한 기능 제공
  • 프로그래머에게 다양한 프로그래밍 스타일 선택의 자유 보장
  • 사용자 정의 타입이 내장 타입과 동등한 수준의 지원과 성능을 갖도록 함
  • 사용하지 않는 기능으로 인한 성능 저하(오버헤드)가 없어야 함 (제로 오버헤드 원칙)
  • 하드웨어에 직접 접근할 수 있는 저수준 기능과 고수준 추상화 기능을 동시에 제공[69]
  • 가능한 한 C 언어와의 호환성 유지 노력

3. 1. 캡슐화

캡슐화는 데이터 구조와 이를 조작하는 메서드를 하나로 묶고, 외부로부터의 직접적인 접근을 제한하여 정보 은닉을 구현하는 객체 지향 프로그래밍의 핵심 원칙이다. 이를 통해 코드의 재사용성을 높이고 유지보수를 용이하게 만들며, 다른 개발자가 클래스의 복잡한 내부 구현을 알 필요 없이 공개된 인터페이스만으로 객체를 사용할 수 있도록 한다.[79][80]

C++에서 캡슐화는 주로 클래스(`class`)를 통해 구현되며, 다음 두 가지 요소를 포함한다.

1. 데이터와 메서드의 결합: 클래스 내부에 멤버 변수(데이터)와 이를 처리하는 멤버 함수(메서드)를 함께 정의한다. C++에서는 멤버 함수가 호출될 때 해당 객체의 메모리 주소값을 가리키는 `this` 포인터가 자동으로 전달된다. 이 `this` 포인터를 통해 멤버 함수는 특정 객체의 멤버 변수에 접근할 수 있으며, 데이터와 이를 처리하는 코드가 논리적으로 결합된다. (`static` 멤버 함수는 특정 객체에 속하지 않으므로 `this` 포인터를 받지 않는다.)

2. 정보 은닉 (Information Hiding): 클래스 외부에서 멤버 변수나 멤버 함수에 대한 접근을 제어한다. C++는 이를 위해 세 가지 접근 지정자(Access Specifier) 키워드를 제공한다.

  • `public`: 클래스 외부를 포함한 어디에서든 접근할 수 있다. 클래스의 사용자가 직접 호출해야 하는 인터페이스 함수들을 주로 `public`으로 선언한다.
  • `protected`: 해당 클래스 내부와 이 클래스를 상속받은 파생 클래스 내부에서만 접근할 수 있다.
  • `private`: 해당 클래스 내부에서만 접근할 수 있다. 클래스의 멤버 변수(데이터)는 외부로부터의 직접적인 수정을 막고 데이터 무결성을 지키기 위해 일반적으로 `private`으로 선언한다.


객체 지향 설계에서는 일반적으로 모든 데이터 멤버를 `private` 또는 `protected`로 선언하고, 외부에서 필요한 최소한의 기능만을 `public` 멤버 함수(인터페이스)로 제공하는 것이 권장된다. 이렇게 데이터 구현의 세부 사항을 숨기면, 클래스 내부 구현 방식이 변경되더라도 공개된 인터페이스만 그대로 유지된다면 클래스를 사용하는 외부 코드에 영향을 주지 않고 유연하게 수정할 수 있다.[130][131]

다음은 C++에서 캡슐화를 구현하는 간단한 예시 코드이다.



class MyObject {

public: // 외부 인터페이스 제공

MyObject() : m_data(0) { } // 생성자: 멤버 변수 초기화

// 은닉된 데이터(m_data)에 접근할 수 있는 public 멤버 함수 (Getter)

int getData() const {

return m_data; // this->m_data 와 동일 (this는 자동으로 전달됨)

}

// 은닉된 데이터(m_data)를 수정할 수 있는 public 멤버 함수 (Setter)

void setData(int value) {

// 필요하다면 데이터 유효성 검사 등을 여기에 추가 가능

m_data = value; // this->m_data = value 와 동일

}

private: // 클래스 내부에서만 접근 가능하도록 데이터 은닉

int m_data; // 멤버 변수

};

int main() {

MyObject obj;

obj.setData(10); // public 멤버 함수 setData()를 통해 데이터 설정

int data = obj.getData(); // public 멤버 함수 getData()를 통해 데이터 읽기

// obj.m_data = 20; // 컴파일 오류 발생: private 멤버 m_data에 직접 접근 불가

return 0;

}



참고로 C++의 구조체(struct) 역시 클래스와 유사하게 멤버 변수, 멤버 함수, 생성자, 소멸자 등을 가질 수 있으며 캡슐화 기능을 동일하게 사용할 수 있다. 다만, 접근 지정자를 명시하지 않았을 경우, 클래스의 멤버는 기본적으로 `private` 접근 권한을 가지는 반면, 구조체의 멤버는 기본적으로 `public` 접근 권한을 가진다는 차이가 있다.

3. 2. 상속

상속은 어떤 클래스가 다른 클래스의 속성(자산)을 물려받아 사용할 수 있게 하는 기능이다.[106][107][108] 기반 클래스로부터 상속을 받을 때는 `public`, `protected`, `private` 중 하나의 접근 지정자를 사용하여 선언한다. 이 접근 지정자는 상속받는 파생 클래스나 전혀 관계없는 다른 클래스가 기반 클래스의 `public` 및 `protected` 멤버에 접근할 수 있는 범위를 결정한다. 일반적으로 '상속'이라고 하면 `public` 상속을 의미하며, 다른 두 가지 방식은 상대적으로 덜 사용된다. 만약 접근 지정자를 생략하면, `class` 키워드로 정의된 클래스는 기본적으로 `private` 상속을 하고, `struct` 키워드로 정의된 구조체는 `public` 상속을 한다. 기반 클래스를 `virtual` 키워드를 사용하여 선언하는 것을 가상 상속이라고 한다. 가상 상속은 상속 관계도 내에서 기반 클래스의 인스턴스가 단 하나만 존재하도록 보장하여, 다중 상속에서 발생할 수 있는 모호성 문제를 일부 해결하는 데 도움을 준다.

'''다중 상속'''은 C++의 특징 중 하나로, 하나의 클래스가 여러 개의 기반 클래스로부터 직접 상속받을 수 있도록 허용한다.[106][107][108] 이를 통해 더 복잡하고 정교한 상속 구조를 설계할 수 있다. 예를 들어, '날으는 고양이'(`FlyingCat`) 클래스를 '고양이'(`Cat`) 클래스와 '날으는 포유류'(`FlyingMammal`) 클래스 양쪽으로부터 상속받아 정의하는 것이 가능하다. 하지만 다중 상속은 구조를 복잡하게 만들 수 있어 주의가 필요하며, C++ 내에서도 종종 논란이 되는 기능이다. 자바나 C#과 같은 다른 객체 지향 언어에서는 클래스 상속은 하나만 허용하는 대신, 여러 개의 인터페이스를 구현(상속)할 수 있도록 하여 다중 상속과 유사한 효과를 내면서도 구조적 복잡성을 줄이려는 접근 방식을 사용한다(인터페이스는 클래스와 달리 멤버 함수의 선언만 제공하고 구현이나 멤버 데이터는 제공하지 않는다). C++에서 인터페이스와 유사한 개념은 순수 가상 함수만으로 이루어진 클래스, 즉 추상 기반 클래스(Abstract Base Class, ABC)로 구현할 수 있다. 이러한 추상 기반 클래스의 멤버 함수는 보통 파생 클래스에서 구체적으로 재정의해야 하며, 암시적으로 상속되지 않는다. C++의 가상 상속은 우월성(dominance)이라는 모호성 해결 기능을 제공하기도 한다.

3. 3. 다형성

다형성은 여러 구현에 대해 하나의 공통된 인터페이스를 제공하여, 객체가 상황에 따라 다르게 동작하도록 하는 기능이다.

C++는 '''정적 다형성'''(컴파일 타임 다형성)과 '''동적 다형성'''(런타임 다형성)을 모두 지원한다. 정적 다형성은 컴파일 시간에 결정되므로 유연성은 떨어지지만 실행 속도가 빠르다는 장점이 있다. 반면, 동적 다형성은 실행 시간에 결정되므로 유연성은 높지만 성능 저하가 발생할 수 있다.

=== 정적 다형성 ===

정적 다형성은 컴파일 시간에 구현 방식이 결정되는 다형성이다. C++에서는 함수 오버로딩과 템플릿을 통해 정적 다형성을 지원한다.

==== 함수 오버로딩 ====

함수 오버로딩은 이름은 같지만 매개변수의 종류나 개수가 다른 여러 함수를 정의하는 기능으로, 임의 다형성(Ad-hoc polymorphism)의 한 예이다. 함수는 매개변수의 개수나 타입에 따라 구분되며, 호출 시 전달되는 인수에 맞춰 적합한 함수가 선택된다. 함수의 반환 타입만으로는 오버로딩된 함수를 구분할 수 없으며, 반환 타입만 다르게 정의하면 컴파일 오류가 발생한다.

함수를 선언할 때 특정 매개변수에 기본값을 지정할 수 있다. 함수 호출 시 해당 매개변수에 대한 인수를 생략하면 지정된 기본값이 사용된다. 인수가 생략된 매개변수에는 기본값이 자동으로 할당된다. 기본 인수를 사용하면 매개변수 개수만 다른 여러 함수를 오버로딩하는 것보다 코드를 간결하게 만들 수 있다.

==== 템플릿 ====

C++ 템플릿은 매개변수 다형성(Parametric polymorphism)을 구현하는 강력한 기능이다. 템플릿을 사용하면 특정 타입에 의존하지 않는 일반적인 코드를 작성할 수 있다.

특히 CRTP(Curiously Recurring Template Pattern) 기법을 사용하면 가상 함수를 이용한 동적 다형성과 유사한 효과를 내는 정적 다형성을 구현할 수 있다. C++ 템플릿은 타입 안전성을 제공하며 튜링 완전하므로, 템플릿 메타 프로그래밍 기법을 통해 컴파일 시간에 복잡한 연산을 수행하거나 코드를 생성하는 데 활용될 수 있다. 템플릿을 사용하면 코드 크기가 비대해진다는 오해가 있지만, 최적화된 컴파일러는 불필요한 코드 생성을 최소화한다.[81]

=== 동적 다형성 ===

동적 다형성은 프로그램 실행 중에 구현 방식이 결정되는 다형성이다. C++에서는 주로 상속과 가상 함수를 통해 동적 다형성을 지원한다. 부모 클래스 포인터나 참조를 통해 자식 클래스의 오버라이딩된 함수를 호출할 때, 실제 객체의 타입에 따라 실행될 함수가 런타임에 결정된다. 이는 코드의 유연성을 높여주지만, 가상 함수 테이블 조회 등으로 인한 약간의 성능 오버헤드가 발생할 수 있다.

3. 4. 템플릿

C++ 템플릿은 제네릭 프로그래밍을 가능하게 하는 기능이다. C++는 함수, 클래스, 별칭, 변수 템플릿을 지원하며, 변수 템플릿은 C++14부터 도입되었다. 템플릿은 형식, 컴파일 시간 상수, 그리고 다른 템플릿 자체를 매개변수로 받아들일 수 있다.

템플릿은 컴파일 시점에 '''인스턴스화'''(instantiation)라는 과정을 통해 실제 코드로 구현된다. 컴파일러는 템플릿의 매개변수 자리에 구체적인 인수(특정 형식이나 값 등)를 넣어 실제 동작하는 함수나 클래스를 생성한다. 만약 특정 인수를 사용한 대체가 구문적으로 불가능하다면, 해당 코드는 "오류가 아닌 치환 실패"(SFINAE, Substitution Failure Is Not An Error)라는 규칙에 따라 오버로딩 후보에서 제외된다.

템플릿은 제네릭 프로그래밍뿐만 아니라, 템플릿 메타 프로그래밍(컴파일 시간에 실행되는 프로그래밍)이나 코드 최적화 등 다양한 목적으로 활용되는 강력한 도구이다. 하지만 이러한 강력함에는 비용이 따른다. 템플릿을 사용하면 각기 다른 인수로 템플릿이 인스턴스화될 때마다 해당 코드의 복사본이 생성되어, 최종적으로 만들어지는 객체 코드의 크기가 커질 수 있다. 그러나 이는 개발자가 수동으로 각 경우에 맞춰 코드를 작성했을 때 생성되는 코드의 양과 비슷하거나 오히려 더 작을 수도 있다.[81] 이는 컴파일 시점에 형식 정보가 소거되고 단일 템플릿 본문만 유지되는 자바(Java)의 제네릭과 같은 런타임 제네릭 방식과는 대조적이다.

템플릿은 매크로와는 다르다. 두 기능 모두 컴파일 시점에 처리되며 조건부 컴파일을 가능하게 하지만, 템플릿은 단순한 어휘 치환에 그치지 않는다. 템플릿은 C++ 언어의 의미 체계와 형식 체계를 이해하고, 엄격한 형식 검사를 바탕으로 복잡한 연산이나 프로그램 흐름 제어를 수행할 수 있다. 반면 매크로는 미리 정의된 기준에 따라 컴파일 과정을 조건부로 제어할 수는 있지만, 새로운 형식을 인스턴스화하거나, 재귀적으로 동작하거나, 형식을 평가하는 등의 작업은 할 수 없으며, 기본적으로 컴파일 전 텍스트 치환 및 포함/제외 역할에 한정된다. 즉, 매크로는 이미 존재하는 심볼을 기반으로 컴파일 흐름을 제어할 뿐, 템플릿처럼 독립적으로 새로운 심볼(형식이나 함수 등)을 만들어낼 수는 없다. 템플릿은 정적 다형성과 제네릭 프로그래밍을 구현하기 위한 핵심 도구이다.

또한, C++ 템플릿은 그 자체로 튜링 완전한 컴파일 시간 메커니즘이다. 이는 이론적으로 컴퓨터 프로그램으로 표현 가능한 모든 계산을 템플릿 메타 프로그래밍을 통해 프로그램 실행 전에 컴파일 단계에서 미리 수행할 수 있음을 의미한다.

요약하자면, 템플릿은 인스턴스화에 사용될 특정 인수를 알지 못한 채 작성된, 컴파일 시간 매개변수화된 함수 또는 클래스이다. 템플릿이 인스턴스화되어 생성된 코드는 해당 인수에 맞춰 직접 작성된 코드와 동일한 성능을 가진다. 이러한 방식으로 템플릿은 코드의 일반적이고 광범위하게 적용 가능한 측면(템플릿 자체에 인코딩됨)과 특정 상황에 맞는 측면(템플릿 매개변수에 인코딩됨)을 분리하여, 성능 저하 없이 높은 수준의 추상화를 가능하게 한다.

3. 5. 예외 처리

런타임 오류나 예기치 않은 상황이 발생했을 때, 프로그램의 정상적인 흐름을 방해하지 않고 이를 처리할 수 있도록 문제 발생 지점에서 처리 가능한 지점까지 제어를 전달하는 메커니즘이다.[83] 이를 통해 오류 처리 코드를 일반적인 로직과 분리하여 코드의 가독성과 유지보수성을 높일 수 있다.[84]

오류가 발생하면 예외 객체가 생성되어 던져지며(throw), 이를 처리할 수 있는 가장 가까운 `catch` 블록에서 포착(catch)된다. 예외가 처리될 때까지 현재 스코프를 벗어나고, 호출 스택을 따라 상위 스코프로 예외가 전파(propagation)된다. 이 과정(스택 풀기, stack unwinding)에서 스택에 생성되었던 지역 객체들의 소멸자가 역순으로 호출되어 자원을 안전하게 해제한다.[85] 예외 객체는 발생한 오류에 대한 정보를 담고 있어, `catch` 블록에서 이 정보를 활용하여 적절한 후속 조치를 취할 수 있다.[86]

Google[87], LLVM[88], Qt[89] 등 일부 C++ 스타일 가이드에서는 예외 사용을 권장하지 않거나 금지하기도 한다.

예외를 발생시킬 가능성이 있는 코드는 `try` 블록 안에 작성한다. 예외는 별도의 `catch` 블록(처리기)에서 처리된다. 하나의 `try` 블록 뒤에는 여러 종류의 예외를 처리하기 위한 여러 개의 `catch` 블록이 올 수 있다.[90]

다음은 예외 처리의 간단한 예시이다.



#include // 입출력 스트림 사용

#include // std::vector 사용

#include // 표준 예외 클래스(std::out_of_range, std::exception) 사용

int main() {

try {

// 정수형 벡터 생성 및 초기화

std::vector vec{3, 4, 3, 1};

// 벡터의 범위를 벗어난 인덱스에 접근 시도 (vec의 유효 인덱스는 0, 1, 2, 3)

int i{vec.at(4)}; // vec.at()은 범위 검사를 수행하며, 범위를 벗어나면 std::out_of_range 예외를 던짐

}

// std::out_of_range 타입의 예외를 처리하는 catch 블록

catch (const std::out_of_range &e) {

// 오류 메시지를 표준 오류 스트림(cerr)에 출력

std::cerr << "오류: 벡터의 범위를 벗어난 접근입니다. 상세 정보: " << e.what() << '\n';

}

// std::exception에서 파생된 다른 모든 표준 라이브러리 예외를 처리하는 catch 블록

catch (const std::exception &e) {

std::cerr << "표준 라이브러리 예외 발생: " << e.what() << '\n';

}

// 위 catch 블록들에서 처리되지 않은 그 외 모든 타입의 예외를 처리하는 catch-all 블록

catch (...) {

std::cerr << "알 수 없는 치명적인 오류 발생\n";

}

}



`throw` 키워드를 사용하여 코드 내에서 의도적으로 예외를 발생시킬 수도 있다. 이렇게 발생된 예외도 일반적인 예외 처리 과정을 통해 처리된다.

어떤 환경에서는 기술적인 제약으로 인해 예외를 사용하기 어려울 수 있다. 예를 들어, 모든 연산이 정해진 시간 안에 완료되어야 하는 임베디드 시스템의 핵심 구성 요소에서는 예외 처리에 소요되는 최대 시간을 예측하기 어렵기 때문에 예외 사용이 부적합할 수 있다.[91]

시그널 처리와는 동작 방식이 다르다. 시그널 핸들러는 일반적으로 오류 발생 지점에서 실행 흐름을 잠시 중단하고 핸들러 함수를 호출하지만, 예외 처리는 오류 발생 지점의 스코프를 완전히 벗어나 스택을 거슬러 올라가며 적절한 `catch` 블록을 찾아 실행한다. 예외를 처리하는 `catch` 블록은 예외가 발생한 함수 내에 있을 수도 있고, 호출 스택 상에 있는 이전 함수 호출 중 하나에 있을 수도 있다.

3. 6. 람다 표현식

C++는 익명 함수 또는 람다 표현식이라고도 하는 기능을 다음과 같은 형식으로 지원한다.

```cpp

[캡처](매개변수) -> 반환형 { 함수 본문 }

```

C++20부터는 람다 표현식의 템플릿 매개변수에 대해 template 키워드를 생략할 수 있다.

```cpp

[캡처]<템플릿 매개변수>(매개변수) -> 반환형 { 함수 본문 }

```

람다가 매개변수를 받지 않고 반환 형식이나 다른 지정자가 사용되지 않는 경우, ()를 생략할 수 있다. 즉, 다음과 같이 작성할 수 있다.

```cpp

[캡처] { 함수 본문 }

```

람다 표현식의 반환 형식은 가능한 경우 자동으로 추론될 수 있다. 예를 들면 다음과 같다.

```cpp

[](int x, int y) { return x + y; } // 반환 형식이 int로 추론됨

[](int x, int y) -> int { return x + y; } // 반환 형식을 int로 명시적으로 지정함

```

[캡처] 목록은 클로저의 정의를 지원한다. 이러한 람다 표현식은 이름 없는 함수 객체에 대한 구문 설탕으로 표준에 정의되어 있다.

4. 객체의 생성과 소멸

C++에서 객체는 클래스를 통해 그 구조가 정의되며, 프로그램 내에서 데이터를 저장하고 기능을 수행하는 기본 단위이다. 객체가 언제 메모리에 생성되고 언제 사라지는지, 즉 객체의 수명(lifetime)은 C++의 메모리 관리 방식과 밀접하게 연관되어 있다. C++는 객체가 메모리에 존재하는 방식과 기간을 결정하는 여러 저장 기간(storage duration)을 정의하며, 이는 객체의 생성 및 소멸 시점을 결정한다.[73]

주요 저장 기간 유형은 다음과 같다.


  • 정적 저장 기간(Static storage duration): 프로그램 시작 시 생성되어 프로그램 종료 시 소멸된다. 전역 객체나 `static` 지역 객체가 해당된다.[74]
  • 스레드 저장 기간(Thread storage duration): 특정 스레드 시작 시 생성되어 해당 스레드 종료 시 소멸된다. `thread_local` 키워드로 선언된 객체가 해당된다.[75]
  • 자동 저장 기간(Automatic storage duration): 함수나 블록 진입 시 생성되어 해당 범위를 벗어날 때 소멸된다. 일반적인 지역 변수가 해당된다.[76]
  • 동적 저장 기간(Dynamic storage duration): `new` 연산자로 생성되고 `delete` 연산자로 소멸된다. 프로그래머가 수명을 직접 관리한다.[77] 스마트 포인터 사용이 권장된다.[78]


이러한 저장 기간에 따라 객체의 생성과 소멸 방식이 달라지며, 구체적인 내용은 하위 섹션에서 자세히 설명한다.

4. 1. 객체의 선언

객체를 구현하기 위해서는 먼저 클래스를 선언하여 객체의 구조를 정의해야 한다. 객체의 구조는 멤버 변수(데이터)와 멤버 함수(메서드)로 구성된다. C++에서 객체는 선언 위치나 방식에 따라 생성 및 소멸 시점이 달라지며, 크게 정적 객체와 동적 객체로 나눌 수 있다.
객체 생성1. 정적 객체:

  • 전역 정적 객체: `main()` 함수가 시작되기 전에 메모리 공간이 할당되고 생성자가 자동으로 실행된다. 이 객체들은 프로그램 실행 시 운영 체제로부터 할당받은 특정 데이터 영역에 생성된다.
  • 지역 정적 객체: 함수나 특정 코드 블록 내에서 선언된 시점에 메모리 공간이 할당되고 생성자가 실행된다. 주로 스택 영역에 할당된다.


2. 동적 객체:

  • `new` 연산자를 사용하여 프로그래머가 원하는 시점에 힙(heap) 메모리 공간에 객체를 생성한다. 생성 시 생성자가 자동으로 실행된다.

객체 소멸

  • 전역 정적 객체: `main()` 함수가 종료된 후, 즉 프로그램이 종료될 때 소멸된다. 생성된 역순으로 소멸자가 호출된다.
  • 지역 정적 객체: 해당 객체가 선언된 함수나 코드 블록이 종료될 때 자동으로 소멸된다.
  • 동적 객체: `delete` 연산자를 사용하여 프로그래머가 명시적으로 메모리에서 해제해야 소멸된다.


C++에서는 C언어의 구조체(`struct`)도 클래스와 거의 동일하게 사용할 수 있다. 구조체 역시 멤버 변수, 멤버 함수, 생성자, 소멸자를 가질 수 있으며 캡슐화도 가능하다. 다만, 멤버에 대한 접근 지정자를 명시하지 않았을 때, 클래스는 기본적으로 `private` 접근 권한을 가지는 반면, 구조체는 `public` 접근 권한을 가진다는 차이가 있다.

4. 2. 접근자

캡슐화객체 지향 프로그래밍에서 데이터와 관련 함수를 하나로 묶고, 내부 구현의 세부 사항을 외부로부터 숨기는 중요한 원칙이다. C++에서는 클래스 멤버(멤버 변수나 멤버 함수)에 대한 접근 권한을 제어함으로써 정보 은닉을 구현하며, 이를 위해 세 가지 접근 지정자 키워드를 사용한다. 이를 통해 개발자는 클래스의 내부 구현을 안전하게 보호하고, 외부에는 필요한 인터페이스만을 노출할 수 있다.

세 가지 접근 지정자는 다음과 같은 접근 수준을 정의한다.

  • `public`: 모든 곳에서 접근이 가능하다. 클래스 외부와 소통하기 위한 인터페이스를 정의할 때 주로 사용된다.
  • `protected`: 해당 클래스 내부와 그 클래스를 상속받은 자식 클래스 내부에서만 접근할 수 있다. 상속 관계에서 자식 클래스에게는 공개하지만, 외부에는 숨기고 싶은 멤버에 사용된다.
  • `private`: 해당 클래스 내부에서만 접근이 가능하다. 클래스의 내부 상태나 구현 세부 사항을 완전히 숨기기 위해 사용되며, 가장 엄격한 접근 제어 수준이다.


객체 지향 설계에서는 일반적으로 클래스의 멤버 변수는 `private` 또는 `protected`로 선언하여 외부에서의 직접적인 접근을 제한하고, 이들 데이터에 접근하거나 조작해야 할 경우 `public`으로 선언된 멤버 함수(메서드)를 통해 간접적으로 상호작용하도록 권장한다. 이러한 방식은 클래스의 내부 구현이 변경되더라도, 클래스를 사용하는 외부 코드에 미치는 영향을 최소화하여 코드의 유지보수성과 안정성을 높이는 데 기여한다.[130][131]

참고로, C++의 구조체(`struct`) 역시 클래스와 유사하게 멤버 변수와 멤버 함수를 가질 수 있지만, 멤버에 대한 기본 접근 지정자에서 차이가 있다. 접근 지정자를 명시하지 않을 경우, 클래스의 멤버는 기본적으로 `private`으로 간주되는 반면, 구조체의 멤버는 `public`으로 간주된다.

4. 3. 객체의 생성

클래스를 선언하여 객체의 구조를 정의한 후, 이를 바탕으로 객체를 생성할 수 있다. 객체는 C 언어의 변수처럼 선언 위치에 따라 생성 및 소멸 방식이 달라진다.

객체를 만드는 과정은 다음과 같다.

# 클래스를 이용해 객체의 구조(멤버 변수와 멤버 함수)를 정의한다.

# 정의된 클래스를 바탕으로 정적 또는 동적으로 객체를 생성한다.

객체는 크게 정적 객체와 동적 객체로 나눌 수 있다.

=== 정적 객체 ===

정적 객체는 선언 위치에 따라 전역 정적 객체와 지역 정적 객체로 구분된다.

  • '''전역 정적 객체''': `main()` 함수가 실행되기 전에 메모리 공간이 할당되고 생성자가 자동으로 호출된다. 이 객체들은 메모리 맵 상의 특정 데이터 영역에 생성되며, 프로그램이 시작될 때 운영 체제로부터 할당받는다. 프로그램이 종료될 때 소멸된다.
  • '''지역 정적 객체''': 함수나 특정 코드 블록 내부에 선언된 시점에서 메모리 공간이 할당되고 생성자가 자동으로 호출된다. 일반적으로 스택 메모리 영역에 생성되며, 해당 함수나 블록의 실행이 끝나면 자동으로 소멸자가 호출되고 메모리에서 사라진다.


=== 동적 객체 ===

동적 객체는 프로그래머가 필요할 때 직접 메모리를 할당하여 생성하고, 사용이 끝나면 명시적으로 해제해야 하는 객체이다.

  • '''생성''': `new` 연산자를 사용하여 힙 메모리 영역에 객체를 생성한다. `new` 연산자는 필요한 메모리 공간을 할당하고 해당 객체의 생성자를 자동으로 호출한다. `new`는 일반적으로 함수 내에서 사용되므로, `main()` 함수 실행 이후에 호출될 수 있다.
  • '''사용''': `new` 연산자는 생성된 객체의 메모리 주소를 반환하며, 이 주소는 포인터 변수에 저장하여 객체에 접근하는 데 사용된다.
  • '''소멸''': `delete` 연산자를 사용하여 명시적으로 객체를 소멸시켜야 한다. `delete`를 호출하면 해당 객체의 소멸자가 호출되고 할당되었던 힙 메모리가 해제된다.


C++의 객체 생성 방식은 C언어에서 전역 변수, 지역 변수를 선언하거나 동적 메모리를 할당하는 방식과 유사한 개념을 따른다.

예를 들어, 특정 코드 블록 안에서 지역 정적 객체를 선언하면, 해당 블록이 시작될 때 객체가 생성되고 생성자가 호출된다. 블록의 실행이 끝나면 해당 객체의 소멸자가 자동으로 호출되고 객체는 사라진다. 이는 함수 내에서 선언된 지역 정적 객체에도 동일하게 적용된다.

4. 4. 멤버 변수

클래스 내부에 선언된 변수를 멤버 변수(member variable)라고 한다. 멤버 변수는 해당 클래스로부터 생성된 객체의 속성이나 상태를 나타낸다. 멤버 변수로는 정수, 부동소수점, 문자 등 기본적인 자료형뿐만 아니라 다른 클래스의 객체도 선언할 수 있다.

객체가 메모리에 생성될 때, 멤버 변수들은 일반적으로 클래스 정의에 선언된 순서대로 메모리 공간을 차지하여 객체의 메모리 구조를 형성한다. 이는 C언어의 struct와 유사한 방식이다.

멤버 함수 내에서는 `this` 포인터를 통해 현재 객체의 멤버 변수에 접근할 수 있다. `this` 포인터는 멤버 함수가 호출될 때 컴파일러에 의해 암묵적으로 전달되는, 해당 객체의 메모리 주소값을 가리키는 포인터이다. 멤버 함수는 이 `this` 포인터를 사용하여 어떤 객체의 멤버 변수를 조작해야 하는지 구별한다.



class MyObject {

public:

int getData() {

// this->m_data 와 동일하게 동작한다.

// 컴파일러는 멤버 변수 접근 시 암묵적으로 this 포인터를 사용한다.

return m_data;

}

void setData(int data) {

// 매개변수 이름과 멤버 변수 이름이 같을 때

// this 포인터를 명시적으로 사용하여 구분할 수 있다.

this->m_data = data;

}

private:

int m_data;

};



멤버 변수는 캡슐화의 원칙에 따라 외부에서의 직접적인 접근을 제한할 수 있다. C++에서는 `public`, `protected`, `private` 키워드를 사용하여 멤버 변수의 접근 수준을 지정한다.

  • `public`: 어떤 외부 코드에서도 접근 가능하다.
  • `protected`: 해당 클래스 및 이 클래스를 상속받은 자식 클래스에서만 접근 가능하다.
  • `private`: 해당 클래스의 멤버 함수 내에서만 접근 가능하다. 외부에서는 접근할 수 없다.


일반적으로 멤버 변수는 `private`으로 선언하여 정보 은닉을 구현하고, 필요한 경우 `public` 멤버 함수(getter 및 setter)를 통해 간접적으로 접근하도록 설계한다.



class MyObject {

public:

MyObject() : m_data(0) {} // 생성자에서 멤버 변수 초기화

int getData() const { // public 멤버 함수(getter)를 통해 private 멤버 변수 값 반환

return m_data;

}

void setData(int data) { // public 멤버 함수(setter)를 통해 private 멤버 변수 값 설정

m_data = data;

}

private: // private 접근 제한자: 클래스 외부에서 m_data에 직접 접근 불가

int m_data; // 멤버 변수 선언

};



특별한 종류의 멤버 변수로 `static` 멤버 변수가 있다. `static`으로 선언된 멤버 변수는 특정 객체에 속하는 것이 아니라 클래스 자체에 속한다. 따라서 해당 클래스의 모든 객체가 공유하는 단 하나의 변수 공간만 존재하며, 객체가 여러 개 생성되어도 `static` 멤버 변수는 하나만 존재한다. `static` 멤버 변수는 객체의 메모리 크기(`sizeof`)에 포함되지 않으며, 프로그램의 정적 저장 기간(static storage duration)을 가지므로 프로그램 시작 시 생성되고 프로그램 종료 시 소멸된다. `static` 멤버 변수는 클래스 외부에서 정의하고 초기화해야 한다.



#include

class MyObject {

public:

static int counter; // static 멤버 변수 선언 (클래스 내)

int id;

MyObject() {

id = ++counter; // 객체 생성 시마다 모든 객체가 공유하는 counter 증가

std::cout << "객체 생성됨 (ID: " << id << "), 현재 객체 수: " << counter << std::endl;

}

~MyObject() {

counter--; // 객체 소멸 시 counter 감소

std::cout << "객체 소멸됨 (ID: " << id << "), 남은 객체 수: " << counter << std::endl;

}

};

// static 멤버 변수 정의 및 초기화 (클래스 외부, 전역 범위)

int MyObject::counter = 0;

int main() {

std::cout << "프로그램 시작. 현재 객체 수: " << MyObject::counter << std::endl;

MyObject obj1; // obj1.id = 1, MyObject::counter = 1

MyObject obj2; // obj2.id = 2, MyObject::counter = 2

std::cout << "obj1의 counter 접근: " << obj1.counter << std::endl; // 객체를 통해서도 접근 가능

std::cout << "obj2의 counter 접근: " << obj2.counter << std::endl; // 값은 동일 (2)

std::cout << "클래스 이름으로 counter 접근: " << MyObject::counter << std::endl; // 클래스 이름을 통해 접근하는 것이 일반적

MyObject* pObj = new MyObject(); // obj3.id = 3, MyObject::counter = 3

delete pObj; // MyObject::counter = 2

std::cout << "main 함수 종료 직전. 현재 객체 수: " << MyObject::counter << std::endl;

// main 함수 종료 시 지역 객체 obj1, obj2 소멸자 호출됨

return 0;

}



클래스 내에서 다른 클래스 타입의 객체를 멤버 변수로 직접 포함할 경우, 두 클래스가 서로를 멤버 변수로 포함하면 무한 재귀에 빠져 객체의 크기를 결정할 수 없는 순환 정의(circular definition) 문제가 발생하여 컴파일 오류가 발생할 수 있다. 이는 클래스 정의 시점에서 멤버 변수의 크기를 알아야 해당 클래스의 전체 크기를 계산할 수 있기 때문이다.

순환 정의 (컴파일 오류)해결 방법 (포인터/참조)
A 클래스는 멤버 변수로 B 객체를 가지려 하고, B 클래스는 멤버 변수로 A 객체를 가지려 한다. 서로의 크기 정의가 완료되지 않아 무한 순환에 빠지므로 컴파일 오류가 발생한다.한쪽(또는 양쪽) 클래스에서 상대방 클래스의 객체 대신, 해당 객체를 가리키는 포인터(`*`)나 참조(`&`)를 멤버 변수로 사용한다. 포인터나 참조 변수의 크기는 가리키는 대상 객체의 크기와 상관없이 시스템에 따라 고정되어 있으므로(예: 32비트 시스템에서 4바이트, 64비트 시스템에서 8바이트), 클래스의 크기를 결정할 수 있게 된다. 전방 선언만으로 포인터나 참조 변수를 선언하는 것은 가능하다.



마찬가지로 클래스가 자기 자신 타입의 객체를 멤버 변수로 직접 포함하는 재귀적인 선언도 크기 결정 문제로 인해 불가능하다. 이 경우에도 포인터나 참조를 사용하여 해결할 수 있으며, 이는 연결 리스트트리와 같은 재귀적 자료 구조를 구현할 때 흔히 사용된다.

재귀적 선언 (컴파일 오류)해결 방법 (포인터/참조)
자기 자신 타입의 객체를 멤버로 가지면 크기를 무한히 계산해야 하므로 불가능하다.자기 자신 타입을 가리키는 포인터나 참조를 멤버로 가지는 것은 가능하다. 포인터/참조의 크기는 고정되어 있기 때문이다.



객체의 실제 메모리 레이아웃은 컴파일러 최적화, 데이터 정렬(padding), 가상 함수 사용 여부 등에 따라 달라질 수 있다. 예를 들어, 가상 함수가 하나라도 포함된 클래스의 객체는 일반적으로 숨겨진 멤버 변수로 가상 함수 테이블을 가리키는 포인터(vptr 또는 vpointer)를 추가로 포함하게 되어 객체의 크기가 커진다.

x86 32비트 환경에서 `virtual` 키워드가 없는 MyObject 클래스 객체의 메모리 구조 예시. 멤버 변수 `age`, `name`, `fdynm`이 순서대로 배치될 수 있다 (패딩에 따라 달라질 수 있음).


x86 32비트 환경에서 `virtual` 소멸자를 사용한 MyObject 클래스 객체의 메모리 구조 예시. 일반적으로 객체 시작 부분에 가상 함수 테이블 포인터(vptr)가 추가되고, 그 뒤에 멤버 변수들이 배치된다.


C++의 struct 역시 클래스와 거의 동일하게 멤버 변수, 멤버 함수, 생성자, 소멸자 등을 가질 수 있다. `class` 키워드와 `struct` 키워드의 주된 차이점은 멤버에 대한 기본 접근 지정자이다. 접근 지정자를 명시하지 않았을 때, `class`는 기본적으로 모든 멤버가 `private`으로 간주되는 반면, `struct`는 기본적으로 모든 멤버가 `public`으로 간주된다. 상속 접근 지정자도 기본값이 다르다 (`class`는 `private` 상속, `struct`는 `public` 상속). 그 외의 기능적인 면에서는 거의 동일하다.

x86 32비트 환경에서 C언어 스타일 struct의 메모리 구조 예시. C++ 클래스와 유사하게 멤버 변수들이 메모리에 배치된다.

4. 5. 멤버 함수

클래스 내부에 정의되어 해당 클래스의 객체가 수행할 수 있는 동작이나 기능을 나타내는 함수를 멤버 함수(member function) 또는 메서드(method)라고 한다. 이는 객체의 행위(behavior)를 정의하며, 객체 지향 프로그래밍의 핵심 요소인 캡슐화를 구현하는 데 사용된다. 캡슐화는 데이터(멤버 변수)와 이를 처리하는 함수(멤버 함수)를 하나로 묶고, 외부로부터의 직접적인 접근을 제한하는 것을 의미한다.

C++에서 멤버 함수는 일반적으로 해당 함수를 호출한 객체 자신의 메모리 주소값을 가리키는 특별한 포인터인 `this`를 암묵적으로 전달받는다. 이 `this` 포인터를 통해 멤버 함수는 자신이 속한 객체의 멤버 변수에 접근하고 조작할 수 있으며, 이를 통해 데이터와 메서드가 효과적으로 결합된다.



#include // 표준 입출력 헤더 포함

// using namespace std; // std 네임스페이스 사용 선언 (main 함수 내에서 개별 사용도 가능)

class MySimpleObject {

public:

// 멤버 함수 선언 (클래스 내부)

void setData(int value); // 데이터를 설정하는 멤버 함수

int getData(); // 데이터를 반환하는 멤버 함수

// 멤버 함수 정의 (클래스 내부)

void printData() {

// 멤버 함수 내에서는 멤버 변수에 직접 접근 가능

// 컴파일러는 이를 암묵적으로 this->m_data로 처리한다.

std::cout << "Data: " << m_data << std::endl; // std:: 접두사 사용

}

private:

int m_data = 0; // 멤버 변수 (데이터), C++11부터 클래스 내 초기화 가능

};

// 멤버 함수 정의 (클래스 외부)

// 'MySimpleObject::'는 이 함수가 MySimpleObject 클래스의 멤버임을 나타낸다.

void MySimpleObject::setData(int value) {

// 매개변수 value를 멤버 변수 m_data에 할당

// 여기서도 암묵적으로 this->m_data = value; 와 같이 동작한다.

m_data = value;

}

int MySimpleObject::getData() {

// 멤버 변수 m_data의 값을 반환

// 암묵적으로 return this->m_data; 와 같다.

return m_data;

}

int main() {

MySimpleObject obj; // MySimpleObject 클래스의 객체 생성

obj.setData(100); // 멤버 함수 호출을 통해 객체의 데이터 설정

obj.printData(); // 멤버 함수 호출을 통해 객체의 데이터 출력 (출력: Data: 100)

int data = obj.getData(); // 멤버 함수 호출을 통해 객체의 데이터 얻기

std::cout << "Returned Data: " << data << std::endl; // std:: 접두사 사용 (출력: Returned Data: 100)

return 0;

}



멤버 함수는 위 예시처럼 클래스 선언 내부에 직접 정의하거나, 클래스 외부에서 `클래스이름::함수이름` 형태로 정의할 수 있다.

모든 멤버 함수가 `this` 포인터를 받는 것은 아니다. `static` 키워드로 선언된 `static` 멤버 함수는 특정 객체에 속하지 않고 클래스 자체에 속하기 때문에 `this` 포인터를 전달받지 않는다. 따라서 `static` 멤버 함수 내에서는 일반 멤버 변수나 `this` 포인터가 필요한 다른 일반 멤버 함수에 직접 접근할 수 없다.

멤버 함수는 객체의 상태를 변경하거나, 상태 정보를 반환하거나, 특정 작업을 수행하는 등 객체가 가져야 할 다양한 기능을 구현하는 데 사용된다. 또한 접근 지정자(`public`, `protected`, `private`)를 통해 외부에서의 접근 수준을 제어함으로써 정보 은닉을 달성하는 데 기여한다. 예를 들어, `private` 멤버 함수는 클래스 내부의 다른 멤버 함수들만 호출할 수 있어 내부 구현 로직을 감추는 데 사용될 수 있다.

4. 5. 1. this

C++에서 클래스의 멤버 함수는 호출될 때, 해당 함수를 호출한 객체 자신의 메모리 주소값을 특별한 포인터 변수인 `this`를 통해 전달받는다. 즉, `this`는 현재 실행 중인 멤버 함수가 속한 객체를 가리키는 포인터이다.

`this` 포인터는 다음과 같은 중요한 역할을 수행한다.

  • 데이터와 메서드의 결합: 객체 지향 프로그래밍의 핵심 요소 중 하나인 캡슐화는 데이터(멤버 변수)와 이를 조작하는 메서드(멤버 함수)를 하나로 묶는 것을 의미한다. C++에서는 멤버 함수가 호출될 때 `this` 포인터를 암묵적으로 전달받음으로써, 해당 함수가 어떤 객체의 멤버 변수에 접근해야 하는지를 명확히 알 수 있게 된다. 이를 통해 데이터와 메서드가 효과적으로 결합된다.
  • 객체 구별: 동일한 클래스로부터 여러 개의 객체가 생성되었을 때, 각 객체는 메모리 상에 서로 다른 위치에 존재한다. 멤버 함수가 호출될 때 전달되는 `this` 포인터는 현재 어떤 객체에 대해 함수가 동작해야 하는지를 구별하는 수단이 된다.
  • 멤버 접근: 멤버 함수 내에서 해당 객체의 멤버 변수나 다른 멤버 함수에 접근할 때 `this` 포인터를 명시적으로 사용할 수 있다. 예를 들어, `this->m_data`와 같이 멤버 변수에 접근하거나 `this->getData()`와 같이 다른 멤버 함수를 호출할 수 있다. 많은 경우 `this->`는 생략 가능하며, 컴파일러가 자동으로 멤버를 찾아준다.




class MyObject {

public:

MyObject(int data) : m_data(data) {} // 생성자에서 멤버 변수 초기화

int getData() {

// 'this->m_data'는 현재 객체의 m_data 멤버를 의미한다.

// 'this->'는 생략 가능하며, 그냥 'm_data'로 써도 동일하다.

return this->m_data;

}

void setData(int data) {

// 매개변수 이름(data)과 멤버 변수 이름(m_data)이 다를 때는

// 'this->' 없이도 구별되지만, 이름이 같다면 'this->'가 필요하다.

// 예: void setData(int m_data) { this->m_data = m_data; }

this->m_data = data;

}

private:

int m_data;

};



`MyObject::getData()`와 같이 클래스 이름과 범위 지정 연산자(`::`)를 사용하여 정의된 멤버 함수들은 실행될 때 자동으로 `this` 포인터가 전달된다. 그러나 `static` 키워드로 선언된 정적 멤버 함수는 특정 객체에 속하지 않고 클래스 자체에 속하기 때문에 `this` 포인터를 전달받지 않는다. 따라서 정적 멤버 함수 내에서는 일반 멤버 변수나 일반 멤버 함수에 직접 접근할 수 없다.

C언어의 `struct`와 비교하면 `this`의 역할을 더 명확히 알 수 있다. C언어에서는 구조체와 관련된 함수를 만들 때, 해당 구조체 변수의 주소를 함수의 인자로 명시적으로 넘겨주어야 한다.



// C언어 스타일의 구조체와 함수

struct MyStruct {

int data;

};

// 구조체 포인터를 명시적으로 첫 번째 인자로 받음

void setMyStructData(MyStruct* p_this, int data) {

p_this->data = data;

}

// C++ 클래스

class MyObject {

public:

void setData(int data) {

// 멤버 함수는 컴파일러에 의해 암묵적으로 'this' 포인터를 전달받음

this->m_data = data;

}

private:

int m_data;

};

int main() {

MyStruct s;

setMyStructData(&s, 10); // 구조체 변수의 주소를 명시적으로 전달

MyObject obj;

obj.setData(20); // 객체를 통해 멤버 함수 호출 시 'this'가 암묵적으로 전달됨

return 0;

}



위 예시처럼 C++의 멤버 함수는 `this` 포인터를 통해 자동으로 객체와 연결되지만, C언어 함수는 그렇지 않다. `this`는 C++가 객체 지향 프로그래밍을 지원하는 핵심적인 메커니즘 중 하나이다.

4. 5. 2. static 멤버 함수

`static` 키워드를 사용하여 선언된 멤버 함수를 `static` 멤버 함수라고 한다. 일반적인 멤버 함수는 호출될 때 해당 객체의 메모리 주소를 가리키는 `this` 포인터가 암묵적으로 전달되어, 이를 통해 객체의 멤버 변수에 접근한다. 그러나 `static` 멤버 함수는 이러한 `this` 포인터를 전달받지 않는다.[41][42][43][44][45][46][47][48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63][64][65][66][67][68][73][74][75][76]

`this` 포인터가 없기 때문에 `static` 멤버 함수는 특정 객체에 속하지 않고 클래스 자체에 속하게 된다. 따라서 객체를 생성하지 않고도 '클래스 이름::함수 이름' 형식으로 호출할 수 있다. 만약 `static` 멤버 함수 내에서 특정 객체의 멤버 변수나 다른 멤버 함수에 접근해야 한다면, 해당 객체에 대한 포인터나 참조를 함수의 인자로 명시적으로 전달해야 한다.[41][42][43][44][45][46][47][48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63][64][65][66][67][68][73][74][75][76]

다음은 `static` 멤버 함수를 사용하는 예시이다.



#include

class A {

public:

int num;

A(int n) { num = n; }

// 일반 멤버 함수: 암묵적으로 'this' 포인터를 사용

int add(int n2) { return (num += n2); }

// static 멤버 함수: 'this' 포인터를 사용하지 않음

// 특정 객체의 멤버에 접근하려면 해당 객체의 포인터(pa)를 받아야 함

static int static_add(A *pa, int n2);

// static 멤버 함수: 객체 멤버와 상관없는 기능을 수행할 수도 있음

static int static_add_simple(int n1, int n2) { return n1 + n2; }

};

// static 멤버 함수의 정의

int A::static_add(A *pa, int n2)

{

// num += n2; // 오류: 'this' 포인터가 없으므로 직접 멤버 변수 'num'에 접근 불가

// error C2597: illegal reference to non-static member 'A::num'

// 인자로 받은 포인터 'pa'를 통해 객체의 멤버 변수에 접근

pa->num += n2;

return pa->num;

}

int main()

{

A a(10); // 객체 'a' 생성, a.num은 10

// static 멤버 함수 호출 (클래스 이름 사용)

// 객체 'a'의 멤버 변수를 변경하기 위해 'a'의 주소(&a)를 전달

int r = A::static_add(&a, 20); // a.num은 10 + 20 = 30이 됨

std::cout << "A::static_add(&a, 20) 결과: " << r << ", a.num: " << a.num << std::endl; // 출력: 30, a.num: 30

// 일반 멤버 함수 호출 (객체 이름 사용)

r = a.add(10); // a.num은 30 + 10 = 40이 됨

std::cout << "a.add(10) 결과: " << r << ", a.num: " << a.num << std::endl; // 출력: 40, a.num: 40

// 객체 멤버와 관련 없는 static 멤버 함수 호출

r = A::static_add_simple(5, 3); // 5 + 3 = 8

std::cout << "A::static_add_simple(5, 3) 결과: " << r << std::endl; // 출력: 8

return 0;

}



`static` 멤버 함수는 특정 객체의 상태에 의존하지 않는 기능을 클래스 내에 정의할 때 유용하다. 예를 들어, 클래스와 관련된 유틸리티 함수나 팩토리 함수 등을 `static` 멤버 함수로 구현할 수 있다. 동작 방식은 캡슐화되지 않은 C 언어의 일반 함수와 유사하지만, 클래스의 이름 공간(namespace) 내에 속하여 해당 클래스와의 연관성을 명확히 한다는 차이가 있다.[41][42][43][44][45][46][47][48][49][50][51][52][53][54][55][56][57][58][59][60][61][62][63][64][65][66][67][68][73][74][75][76]

아래 표는 C 스타일의 `struct` 사용 함수, 일반 멤버 함수, `static` 멤버 함수의 차이를 보여준다.

C 스타일 `struct` 사용 함수일반 멤버 함수`static` 멤버 함수


5. 표준 라이브러리

C++98로 승인된 초안 "작업 문서" 표준. 크기의 절반가량이 C++ 표준 라이브러리에 할당되었다.


C++ 표준은 핵심 언어와 표준 라이브러리, 이 두 부분으로 구성된다. C++ 프로그래머는 모든 주요 C++ 구현에서 표준 라이브러리를 사용할 수 있을 것으로 기대한다. 표준 라이브러리는 다양한 기능을 제공하며, 주요 내용은 다음과 같다.

  • 자료 구조 및 컨테이너: 집계 형식(벡터, 리스트, , 집합, 큐, 스택, 배열, 튜플 등)
  • 알고리즘: 검색(binary_search), 정렬, 순회(for_each), 임의 섞기(random_shuffle) 등 다양한 알고리즘
  • 입출력: iostream을 이용한 콘솔 및 파일 입출력 기능
  • 파일 시스템: 파일 및 디렉토리 조작 기능 (C++17부터 표준 포함)
  • 문자열 처리: 문자열 클래스 및 정규 표현식 지원
  • 지역화: 다양한 언어 및 문화권 지원 기능
  • 메모리 관리: 스마트 포인터를 통한 자동 메모리 관리 지원
  • 동시성: 멀티스레딩 라이브러리 및 원자 연산 지원 (C++11부터 표준 포함)
  • 유틸리티: 시간 유틸리티(측정, 현재 시간 등), 난수 생성기, 예외 처리 지원 기능
  • C 표준 라이브러리 호환성: C++ 형식 시스템에 맞게 약간 수정된 C 표준 라이브러리 포함


C++ 라이브러리의 상당 부분은 알렉산더 스테파노프가 설계한 표준 템플릿 라이브러리(STL)를 기반으로 한다. STL은 객체 컬렉션으로서의 컨테이너, 컨테이너에 배열처럼 접근하게 해주는 반복자, 그리고 검색이나 정렬 같은 작업을 수행하는 알고리즘 등의 유용한 도구를 제공한다. 템플릿을 사용하면 특정 컨테이너 타입에 구애받지 않고 범용적으로 작동하는 알고리즘을 작성할 수 있다.[92] C++ 표준에서는 공식적으로 "STL"이라는 용어를 사용하지 않지만, 표준 라이브러리의 다른 부분(입출력 스트림, 국제화, 진단 등)과 구분하기 위해 여전히 널리 사용되는 용어이다.[92]

C++ 표준 라이브러리의 기능은 C언어와 마찬가지로 `#include` 지시문을 사용하여 표준 헤더를 포함함으로써 사용할 수 있다. C++ 표준 라이브러리는 105개의 표준 헤더를 제공하며, 그중 일부는 더 이상 사용되지 않는다.

다양한 실행 환경을 고려하여 GUI 관련 라이브러리는 표준에 포함되어 있지 않다. 대부분의 C++ 컴파일러는 표준을 준수하는 C++ 표준 라이브러리 구현을 제공하며, STLPort와 같이 컴파일러에 독립적인 구현체도 존재한다.

6. C++ Core Guidelines

C++ 코어 가이드라인[93]은 C++의 창시자인 비야네 스트롭스트룹과 C++ ISO 작업 그룹 의장인 허브 서터가 주도하는 계획이다. 이는 프로그래머가 C++11 및 그 이후 버전의 언어 표준에 대한 모범 사례를 사용하여 '모던 C++'을 작성하도록 돕고, 컴파일러 및 정적 검사 도구 개발자가 잘못된 프로그래밍 관행을 식별하는 규칙을 만드는 것을 목표로 한다.

주요 목표는 형식 및 자원이 안전한 C++ 코드를 효율적이고 일관되게 작성하는 것이다.

코어 가이드라인은[94] 2015년 CPPCon의 개막 기조연설에서 발표되었다.

가이드라인에는 코어 가이드라인을 구현하고 규칙을 적용하는 정적 검사 도구를 위한 헤더 전용 라이브러리인 가이드라인 지원 라이브러리(Guideline Support Library, GSL)[95]가 함께 제공된다.[96]

7. C 언어와의 호환성

C 언어에 객체지향 프로그래밍 지원을 위한 내용이 추가된 형태라고 볼 수도 있지만[152], C++는 종종 C의 상위 집합(superset)으로 여겨지기도 한다. 초기 C++는 C 위에 놓인 트랜스레이터로 구현되어 C++ 프로그램을 C 프로그램으로 변환한 후 C 컴파일러로 컴파일하는 방식이었고, 이 시기에는 C 언어에 대해 상위 호환성을 가졌다.

그러나 현재 C 언어와 C++ 사이에는 엄격한 호환성이 없다.[98][139] 대부분의 C 코드는 C++에서 쉽게 컴파일되지만, 유효한 C 코드가 C++에서는 유효하지 않거나 다르게 동작하는 몇 가지 차이점이 존재한다. 예를 들어, C 언어에서는 범용 포인터 void*를 다른 타입의 포인터로 암시적으로 변환할 수 있지만, C++에서는 형식 안전성을 위해 캐스트 연산자를 사용하여 명시적으로 변환해야 한다. 또한 C++는 new, class 등 많은 새로운 키워드를 정의하는데, 이 키워드들이 기존 C 프로그램에서 식별자(변수 이름 등)로 사용되었다면 C++에서는 컴파일 오류가 발생할 수 있다.

C 언어 표준이 개정되면서 C++의 일부 기능이 C 언어에 도입되기도 했다. 예를 들어, C99 표준에서는 줄 단위 주석(//)이나 선언과 코드를 섞어 쓰는 것 등이 C 언어 표준에 포함되어 일부 비호환성이 해소되었다.[99] 반면, C99는 가변 길이 배열(Variable Length Array, VLA), 기본적인 복소수 자료형, 지정된 초기화(designated initializer), 복합 리터럴(compound literal), restrict 키워드 등 C++에서는 지원하지 않거나 호환되지 않는 새로운 기능을 다수 도입하여 C++가 C의 완전한 상위 집합이 아니게 되었다.[99][140] C99에서 도입된 기능 중 일부는 이후 C++11 표준에 포함되었지만[100][101][102], 여전히 모든 기능이 호환되는 것은 아니다. 예를 들어 C++11에서는 문자열 리터럴을 char*에 할당하는 것을 금지하는 등 새로운 비호환성이 생기기도 했다 (C에서는 여전히 허용됨). C11 표준에서는 C99에서 추가된 가변 길이 배열이나 복소수형 등이 선택적 기능으로 변경되었다.[141][142]

C 코드와 C++ 코드를 함께 사용해야 할 경우, 두 언어 간의 링키지(linkage) 방식을 통일해야 한다. 이를 위해 C와 C++ 양쪽에서 호출하거나 사용될 함수는 C 링키지를 사용하도록 extern "C" 키워드를 사용하여 선언해야 한다. 이는 개별 함수 선언 앞에 붙이거나, 여러 함수 선언을 extern "C" { ... } 블록으로 묶어서 지정할 수 있다. C 링키지를 사용하는 함수는 C++의 이름 매글링(name mangling) 규칙을 따르지 않으므로, 함수 오버로딩과 같이 이름 매글링에 의존하는 C++ 기능을 사용할 수 없다.

이처럼 엄밀한 의미에서 C++는 C의 상위 호환 언어는 아니지만[124][125], C/C++ 간의 상호 운용성이 잘 지원되기 때문에 C 표준 라이브러리의 함수 대부분을 C++에서도 큰 문제 없이 사용할 수 있다는 점은 C++의 중요한 장점 중 하나이다.

참조

[1] 웹사이트 Overview of modules in C++ https://learn.micros[...] Microsoft 2023-04-24
[2] 서적 History of programming languages---II ACM 1996
[3] 웹사이트 C++20: Reaching for the Aims of C++ - Bjarne Stroustrup - CppCon 2021 https://www.youtube.[...] CppCon 2021-12-16
[4] 간행물 Thriving in a crowded and changing world: C++ 2006–2020 Association for Computing Machinery (ACM) 2020-06-12
[5] 기타
[6] 간행물 C# 2.0 for C++ and Java programmer: conference workshop 2007-05-00
[7] 웹사이트 Chapel spec (Acknowledgements) https://chapel-lang.[...] Cray Inc 2015-10-01
[8] 웹사이트 Rich Hickey Q&A http://www.codequart[...]
[9] 웹사이트 Cracking The Java Programming Interview :: 2000+ Java Interview Que/Ans https://books.google[...] 2014-07-28
[10] 웹사이트 Scaling JS++: Abstraction, Performance, and Readability https://www.onux.com[...] 2017-05-01
[11] 웹사이트 The evolution of an extension language: a history of Lua https://www.lua.org/[...]
[12] 웹사이트 FAQ Nim Programming Language https://nim-lang.org[...]
[13] 웹사이트 9. Classes — Python 3.6.4 documentation https://docs.python.[...]
[14] 웹사이트 Influences - The Rust Reference https://doc.rust-lan[...]
[15] 서적 The C++ Programming Language https://archive.org/[...] Addison-Wesley
[16] 웹사이트 Lecture:The essence of C++. University of Edinburgh. https://www.youtube.[...] 2014-05-06
[17] 웹사이트 C++ Applications http://www.stroustru[...] 2014-02-17
[18] 웹사이트 Bjarne Stroustrup's Homepage http://www.stroustru[...]
[19] 웹사이트 C++ IS schedule http://www.open-std.[...]
[20] 웹사이트 C++; Where it's heading https://dzone.com/ar[...]
[21] 메일링리스트 Re: [RFC] Convert builin-mailinfo.c to use The Better String Library https://lwn.net/Arti[...] 2007-09-06
[22] 메일링리스트 Re: Efforts to attract more users? http://harmful.cat-v[...] 2010-07-12
[23] 웹사이트 Dr. Dobb's: Interview with Ken Thompson https://www.drdobbs.[...] 2011-05-18
[24] 서적 Coders at Work: Reflections on the Craft of Programming https://books.google[...] Apress 2009-09-16
[25] 웹사이트 C++ in Coders at Work https://gigamonkeys.[...] 2009-10-16
[26] 웹사이트 An Interview with Donald Knuth http://www.drdobbs.c[...] 2009-10-16
[27] 웹사이트 (La)TeX Navigator http://tex.loria.fr/[...]
[28] 웹사이트 Bjarne Stroustrup's FAQ: When was C++ invented? http://www.stroustru[...] 2010-03-07
[29] 웹사이트 Evolving a language in and for the real world: C++ 1991-2006 http://stroustrup.co[...]
[30] 웹사이트 A History of C ++ : 1979− 1991 http://www.stroustru[...]
[31] 웹사이트 The C++ Programming Language
[32] 웹사이트 The C++ Programming Language
[33] 웹사이트 Trip report: Summer ISO C++ standards meeting (Oulu) https://herbsutter.c[...] 2016-06-30
[34] 웹사이트 N4817: 2020 Prague Meeting Invitation and Information http://open-std.org/[...] 2019-11-06
[35] 웹사이트 Current Status https://isocpp.org/s[...]
[36] 웹사이트 C++20 Approved -- Herb Sutter https://isocpp.org/b[...] 2020-09-08
[37] 보도자료 Computer Science Pioneer Bjarne Stroustrup to Receive the 2018 Charles Stark Draper Prize for Engineering https://www.nae.edu/[...] National Academy of Engineering 2018-01-03
[38] 웹사이트 TIOBE Index for November 2024 https://www.tiobe.co[...] TIOBE Company 2024-11-01
[39] 웹사이트 Bjarne Stroustrup's FAQ – Where did the name "C++" come from? http://www.stroustru[...] 2008-01-16
[40] 웹사이트 C For C++ Programmers https://web.archive.[...] Northeastern University
[41] 웹사이트 ISO/IEC 14882:1998 https://www.iso.org/[...] International Organization for Standardization
[42] 웹사이트 ISO/IEC 14882:2003 https://www.iso.org/[...] International Organization for Standardization
[43] 웹사이트 ISO/IEC 14882:2011 https://www.iso.org/[...] International Organization for Standardization
[44] 웹사이트 ISO/IEC 14882:2014 https://www.iso.org/[...] International Organization for Standardization
[45] 웹사이트 ISO/IEC 14882:2017 https://www.iso.org/[...] International Organization for Standardization
[46] 웹사이트 ISO/IEC 14882:2020 https://www.iso.org/[...] International Organization for Standardization
[47] 웹사이트 ISO/IEC 14882:2024 https://www.iso.org/[...] International Organization for Standardization
[48] 웹사이트 We have an international standard: C++0x is unanimously approved https://herbsutter.c[...] 2011-08-12
[49] 웹사이트 The Future of C++ https://channel9.msd[...]
[50] 웹사이트 We have C++14! : Standard C++ https://isocpp.org/b[...]
[51] 웹사이트 Trip report: Summer ISO C++ standards meeting (Toronto) https://herbsutter.c[...] 2017-07-15
[52] 웹사이트 ISO/IEC TR 18015:2006 https://www.iso.org/[...] International Organization for Standardization
[53] 웹사이트 ISO/IEC TR 19768:2007 https://www.iso.org/[...] International Organization for Standardization
[54] 웹사이트 ISO/IEC TR 29124:2010 https://www.iso.org/[...] International Organization for Standardization
[55] 웹사이트 ISO/IEC TR 24733:2011 https://www.iso.org/[...] International Organization for Standardization
[56] 웹사이트 ISO/IEC TS 18822:2015 https://www.iso.org/[...] International Organization for Standardization
[57] 웹사이트 ISO/IEC TS 19570:2015 https://www.iso.org/[...] International Organization for Standardization
[58] 웹사이트 ISO/IEC TS 19841:2015 https://www.iso.org/[...] International Organization for Standardization
[59] 웹사이트 ISO/IEC TS 19568:2015 https://www.iso.org/[...] International Organization for Standardization
[60] 웹사이트 ISO/IEC TS 19217:2015 https://www.iso.org/[...] International Organization for Standardization
[61] 웹사이트 ISO/IEC TS 19571:2016 https://www.iso.org/[...] International Organization for Standardization
[62] 웹사이트 ISO/IEC TS 19568:2017 https://www.iso.org/[...] International Organization for Standardization
[63] 웹사이트 ISO/IEC TS 21425:2017 https://www.iso.org/[...] International Organization for Standardization
[64] 웹사이트 ISO/IEC TS 22277:2017 https://www.iso.org/[...] International Organization for Standardization
[65] 웹사이트 ISO/IEC TS 19216:2018 https://www.iso.org/[...] International Organization for Standardization
[66] 웹사이트 ISO/IEC TS 21544:2018 https://www.iso.org/[...] International Organization for Standardization
[67] 웹사이트 ISO/IEC TS 19570:2018 https://www.iso.org/[...] International Organization for Standardization
[68] 웹사이트 ISO/IEC TS 23619:2021 https://www.iso.org/[...] International Organization for Standardization
[69] 웹사이트 Stroustrup: Thoughts on C++17 - An Interview https://www.infoq.co[...] 2015-04-30
[70] 서적 The C++ Programming Language Addison-Wesley
[71] 웹사이트 Open issues for The C++ Programming Language (3rd Edition) http://www.stroustru[...] 2014-05-05
[72] 웹사이트 Can I write "void main()"? http://www.stroustru[...] 2020-07-02
[73] 논문 Programming Languages – C++11 Draft (n3797) https://www.open-std[...] ISO/IEC 2018-10-02
[74] 논문 Programming Languages – C++11 Draft (n3797) https://www.open-std[...] ISO/IEC 2018-10-02
[75] 논문 Programming Languages – C++11 Draft (n3797) https://www.open-std[...] ISO/IEC 2018-10-02
[76] 논문 Programming Languages – C++11 Draft (n3797) https://www.open-std[...] ISO/IEC 2018-10-02
[77] 논문 Programming Languages – C++11 Draft (n3797) https://www.open-std[...] ISO/IEC 2018-10-02
[78] 웹사이트 C++ Core Guidelines https://isocpp.githu[...] 2020-02-09
[79] 서적 C++ Coding Standards: 101 Rules, Guidelines, and Best Practices Addison-Wesley
[80] 서적 Industrial Strength C++ https://archive.org/[...] Prentice Hall
[81] 웹사이트 Nobody Understands C++: Part 5: Template Code Bloat https://articles.emp[...] EmptyCrate Software. Travel. Stuff. 2010-03-08
[82] 서적 The C++ Programming Language Addison-Wesley
[83] 웹사이트 C and C++ Exceptions | Templates http://www.cl.cam.ac[...] 2013
[84] 서적 The C++ Programming Language Addison Wesley
[85] 서적 The C++ Programming Language Addison Wesley
[86] 서적 The C++ Programming Language Addison Wesley
[87] 웹사이트 Google C++ Style Guide https://google.githu[...] 2019-06-25
[88] 웹사이트 LLVM Coding Standards https://llvm.org/doc[...] 2019-06-25
[89] 웹사이트 Coding Conventions https://wiki.qt.io/C[...] 2019-06-26
[90] 서적 The C++ Programming Language Addison Wesley
[91] 서적 The C++ Programming Language Addison Wesley
[92] 웹사이트 An Interview with A. Stepanov http://www.stlport.o[...] 2015-10-08
[93] 웹사이트 C++ Core Guidelines https://isocpp.githu[...] 2020-02-09
[94] 웹사이트 Bjarne Stroustrup announces C++ Core Guidelines : Standard C++ https://isocpp.org/b[...] 2020-03-31
[95] 웹사이트 microsoft/GSL https://github.com/m[...] 2021-07-18
[96] 웹사이트 Using the C++ Core Guidelines checkers https://docs.microso[...] 2020-03-31
[97] 웹사이트 C++ ABI Summary https://mentorembedd[...] 2001-03-20
[98] 웹사이트 Bjarne Stroustrup's FAQ – Is C a subset of C++? http://www.stroustru[...] 2014-05-05
[99] 웹사이트 C9X – The New C Standard http://home.datacomm[...] 2008-12-27
[100] 웹사이트 C++0x Support in GCC https://gcc.gnu.org/[...] 2010-10-12
[101] 웹사이트 C++0x Core Language Features In VC10: The Table https://blogs.msdn.c[...] 2010-10-12
[102] 웹사이트 Clang - C++98, C++11, and C++14 Status https://clang.llvm.o[...] Clang.llvm.org 2013-05-12
[103] 서적 プログラミング言語C++ 第4版
[104] 서적 C++の設計と進化
[105] 서적 プログラミング言語C++ 第4版
[106] 웹사이트 Bjarne Stroustrup's FAQ - When was C++ invented? http://public.resear[...] 2006-05-30
[107] 서적 The Annotated C++ Reference Manual Addison-Wesley Professional
[108] 서적 The Annotated C++ Reference Manual シイエム・シイ
[109] 표준 ISO/IEC 14882:1998 http://www.iso.org/i[...]
[110] 표준 ISO/IEC 14882:2003 http://www.iso.org/i[...]
[111] 표준 ISO/IEC TR 19768:2007 http://www.iso.org/i[...]
[112] 표준 ISO/IEC 14882:2011 http://www.iso.org/i[...]
[113] 표준 ISO/IEC 14882:2014 http://www.iso.org/i[...]
[114] 표준 https://www.iso.org/[...]
[115] 표준 https://www.iso.org/[...]
[116] 웹사이트 We have C++14! : Standard C++ http://isocpp.org/bl[...]
[117] 웹사이트 Current Status https://isocpp.org/s[...] 2020-09-07
[118] 웹사이트 C++20 Approved -- Herb Sutter https://isocpp.org/b[...] 2020-09-08
[119] 웹사이트 ISO/IEC 14882:2020 https://www.iso.org/[...] 2021-03-16
[120] 웹사이트 Working Draft, Standard for Programming Language C ++ http://open-std.org/[...] 2021-03-16
[121] 웹사이트 Business Plan and Convener's Report: ISO/IEC JTC1/SC22/WG21 (C++) http://www.open-std.[...] 2021-03-16
[122] 웹사이트 Upcoming Meetings, Past Meetings https://isocpp.org/s[...] 2021-03-16
[123] 웹사이트 WG21 2020-11 Virtual Meeting: Minutes of Meeting http://www.open-std.[...] 2021-03-16
[124] 웹사이트 C++: as close as possible to C – but no closer https://isocpp.org/f[...] 2016-11-19
[125] 웹사이트 Stroustrup: FAQ Is C a subset of C++? http://www.stroustru[...] 2016-11-19
[126] 서적 『C++の設計と進化』
[127] 서적 The C++ Programming Language Addison-Wesley 2000
[128] 웹사이트 Open issues for The C++ Programming Language (3rd Edition) http://www.research.[...]
[129] 웹사이트 式 - cppreference.com https://ja.cpprefere[...]
[130] 서적 C++ Coding Standards: 101 Rules, Guidelines, and Best Practices Addison-Wesley 2004
[131] 서적 Industrial Strength C++ Prentice Hall 1997
[132] 서적 The C++ Programming Language Addison-Wesley 2000
[133] 웹사이트 Parsing C++ at nobugs.org http://www.nobugs.or[...] Nobugs.org 2009-07-03
[134] 웹사이트 Why We Can’t Afford Export http://anubis.dkuug.[...]
[135] 웹사이트 Minutes of J16 Meeting No. 36/WG21 Meeting No. 31, April 7-11, 2003 http://www.open-std.[...] 2006-09-04
[136] 웹사이트 C++ ABI http://www.codesourc[...] 2006-05-30
[137] 뉴스 LLVM Clang、C++11にフル対応 https://news.mynavi.[...] マイナビニュース 2013-09-07
[138] 웹사이트 GCC 4.8 Release Series — Changes, New Features, and Fixes - GNU Project https://gcc.gnu.org/[...] 2022-11-07
[139] 웹사이트 Bjarne Stroustrup's FAQ - Is C a subset of C++? http://public.resear[...] 2008-01-18
[140] 웹사이트 C9X -- The New C Standard http://home.datacomm[...] 2008-12-27
[141] 섹션 可変長配列
[142] 웹사이트 C言語の最新事情を知る: C99の仕様 - Build Insider https://www.buildins[...]
[143] 웹인용 ISO/IEC 14882:1998 https://www.iso.org/[...] International Organization for Standardization 2018-11-23
[144] 웹인용 ISO/IEC 14882:2003 https://www.iso.org/[...] International Organization for Standardization 2018-11-23
[145] 웹인용 ISO/IEC 14882:2011 https://www.iso.org/[...] International Organization for Standardization 2018-11-23
[146] 웹인용 ISO/IEC 14882:2014 https://www.iso.org/[...] International Organization for Standardization 2018-11-23
[147] 웹인용 ISO/IEC 14882:2017 https://www.iso.org/[...] International Organization for Standardization 2017-12-02
[148] 웹인용 ISO/IEC 14882:2020 https://www.iso.org/[...] International Organization for Standardization 2020-12-16
[149] 웹인용 Bjarne Stroustrup's FAQ: When was C++ invented? http://www.stroustru[...] 2010-03-07
[150] 웹인용 A History of C ++ : 1979− 1991 http://www.stroustru[...]
[151] 웹인용 The C++ Programming Language http://www.stroustru[...]
[152] text



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com