1983년 C언어에서 직접적으로 파생된 프로그래밍 언어. 비아네 스트로스트룹이 1980년대 C 언어를 바탕으로 만든 언어다.
참고로 C 계열 언어에서 "++"라는 것은 1을 더해서 원래 변수에 대입하라는 뜻이다.
쓸 때는 C++라고 쓰고 읽을 때는 시 플러스 플러스, 혹은 시플플, 씨뿔뿔 이라고 읽는다.
연세가 꽤 있으신 교수님 중에는 간혹 시 더블 플러스라고 읽는 경우도 있다. 미국에서는 그냥 CPP라고 읽는다.
C는 옛날부터 많이 쓰는 언어였다.
하지만 그래픽은 아직 발전하지, 아니 아예 없었다.
그래서 우리가 따로 C++이라는 언어를 만든 거다.
초창기에는 되게 많이 쓰였다.
Minecraft라는 유명한 게임도 C++로 만들어졌고, 언더테일도 C++로 만들어졌다.
하지만 새로운 언어가 유행하면서 C++은 밀리기 시작했다. 그래픽, 네트워크, 계산, 빅데이터, 인공지능까지 모든게 가능한 java, javascript, python 이 셋이 나타나면서 C++은 밀렸다.
하지만 쓸모가 있는 언어기 때문에 C++, C는 아직 사용되고 있다.
아, C언어도 밀렸다는 예기를 안해줬
나? 그리고 무엇보다 중요한것은 객체지향을 그냥 끼워 맟추었단 얘기다.
C++에서는 객체지향이 잘 안맞나보다.
C의 문법에 OOP 개념을 추가하고 일반화 프로그래밍의 요소가 되는 STL을 붙였다.
그래서 대부분의 C 프로그램은 C++ 컴파일러에서도 문제없이 컴파일된다.
초기 C++ 컴파일러는 일단 C++ 코드를 C로 변환하고 그걸 C로 컴파일하는 방식을 사용했을 정도. 하지만 OOP나 일반화 프로그래밍이란 것은 단순한 문법이 아니라 코딩의 패러다임을 말한다.
그래서 C++ 방식으로 코딩하려면 해당 코드에서 C++에 새로 도입된 것을 추가하는 게 아니라 설계부터 시작해서 완전히 새로 해야 하는 경우가 많으므로, 초심자 입장에서는 서로 다른 별개의 언어로 보고 접근하는 것이 안전하다.
그래서 C로 프로그래밍에 발을 들어 놓은 후 C++/Java로 업그레이드 테크를 타는 학생에게 C++ 프로그래밍을 해 오라 하면, 잘해봐야 C++의 입출력 객체를 이용하는 정도를 넘지 못하고 절차적 프로그래밍을 그대로 따라가는 영락없는 C 프로그램이 튀어나오기 일쑤다.
그 이유는 C++의 객체지향이 이해하기가 그렇게 만만한 개념이 아닌 데다가 C++의 객체지향은 C를 유지하면서 그대로 얹어놔서 기묘하기 그지없으므로 다른 객체지향 언어에서보다 잘 다루는데 더 많은 공부가 필요하다.
재밌는 것은, 반대로 C++ -> C 테크도 만만치가 않다.
C++이 C의 모든 기능을 포괄하고 있으므로 C++을 할 줄 알면 C도 할 줄 안다고 생각하기 쉽지만, 사실 C++ 이 명시적으로 비교적 간단히 사용할 수 있도록 제공하는 기능들을 C에서는 암묵적으로 여러가지 수많은 '트릭'을 통해서 쥐어짜 내듯이 만들어 사용하는 경우가 많다.
incomplete type declaration 트릭을 이용하여 캡슐화를 흉내내고, 매크로와 컴파일러 확장을 이용해서 type-generic function을 만들어 쓰고, struct hack을 이용하여 vector를 흉내 내는 식이다.
게다가, 저런 트릭은 언어 차원에서 정식으로 제공한다기보다 말 그대로 '트릭'에 가까우므로 이상한 조건들이 붙는 경우가 종종 있고, 그것들을 정확히 파악하고 있지 않으면 상당히 찾아내기 어려운 에러를 내는 경우도 많다.
말 그대로 C와 C++은 완전히 다른 언어로 파악하고 접근하는 것이 좋다. "잘 짜인 C 프로그램은 C++ 컴파일러로 컴파일할 수 있어야 한다"는 말도 C99가 나오면서 틀린 말이 되어버리기도 했고...
그래서 많은 대학에서 컴공 1학년 때 C를 먼저 가르치고 C++를 가르치지만, 교수가 절차지향이 머리에 굳어버린다며 컴공에서 C 대신 C++과 객체를 먼저 가르치고 C는 아예 건드리지도 않고 다른 하드웨어 관련 학과에서만 가르치는 대학들도 많다.
객체지향만 배운다면 Python으로 가도 되지만, 포인터 등을 통해 메모리와 각종 Low Level적인 프로그래밍과 객체지향을 함께 배울 수 있기 때문이다.
C++는 서식을 이용한 일반화 프로그래밍을 악용[7] 응용해서 컴파일 시점에 계산 등을 하는 TMP이라는 것이 존재한다.
배우기는 어렵고 알아보기도 힘들고 오류 찾기도 힘들지만 알아 두면 은근 써먹을 데가 많다.
O(1)의 위엄! 하지만 여차하다가 바이너리 크기가 n배 증가하는 대참사가 벌어질 수도 있다. 잘만 구현하면 실행 시간을 잃지 않으면서도 컴파일 시점에 다양한 처리나 계산이 가능하므로 라이브러리 구현에 종종 이용된다.
이는 C++ 템플릿의 고유한 기능을 이용하는 것으로 다른 언어에서는 비슷한 것도 찾기 힘들다.
C++은 객체지향 프로그래밍을 지원하지만, C++의 객체지향은 다른 객체지향 언어에서와는 성격이 좀 다르다.
대부분의 객체지향 언어에서는 많은 부분을 런타임에 처리하며 메모리를 자동으로 관리하는 반면, C++에서는 최대한 많은 것을 컴파일 타임에 처리하는 것을 지향하며 메모리 등을 프로그래머가 직접 관리하게 하기 때문에 전반적인 클래스 디자인 자체가 상당한 차이를 보이게 된다. Java 등의 다른 객체지향 언어에서와 같은 방식으로 C++ 클래스를 디자인하면 거의 틀림없이 컴파일이 제대로 안 되거나 메모리 문제가 발생한다.
JAVA->C++ 테크를 탄 학생이라면 처음에는 메모리가 줄줄 새는 프로그램을 만들게 될 것이다.
반면 C++ 스타일로 다른 객체지향 언어에서 프로그래밍을 하는 경우 특별히 안 될 것은 없지만, 해당 언어의 스타일로 작성한 코드에 비해 시간이 많이 걸리고 너저분해 보이며 클래스 구조가 경직되어 수정하기 어려워진다.
대표적인 예가 함수 내부에서 객체를 동적으로 생성해서 그 포인터를 리턴하는 것. C++에서는 이는 메모리 문제를 일으키기 딱 맞는 방식이라서 클래스 디자인 단계에서 이런 종류의 함수가 필요없게 하기 위한 고려가 필요하지만, 가비지 컬렉션이 자동으로 되는 언어에서는 매우 흔히 사용되는 방법이다. 이런 차이 때문에, Java, Smalltalk 등의 언어를 먼저 접한 프로그래머들은 C++의 객체지향이 짝퉁이라며 싫어하기도 한다.
다만 이런 제한이 생기는 건 오래된 스타일의 C++ 코드에서나 그런 것이고, Modern C++에서는 스마트 포인터를[13] move하는 방식으로 완전히 같은 문법이 구현 가능하기 때문에 더 이상 해당이 없는 사항이다.
이러한 차이가 생기는 것은 대부분의 객체지향 언어는 직접적으로 Smalltalk의 영향을 받은 반면, C++는 Smalltalk의 보다 먼저 객체지향의 초보적인 개념을 제시한 시뮬레이션 전용 언어인 Simula에서 직접 영향을 받았기 때문이다.
이는 C 프로그램과의 호환성을 고려한 결과이기도 하지만, 기본적으로 C++에서 프로그램의 성능을 희생시키지 않기 위해서였다.
Smalltalk의 경우 당시의 기술적 한계도 있고 해서 C보다 대체로 수십 배 정도 느렸고, 이는 C++에서 지향하는 결과가 아니었기 때문이다.
객체지향 등이 일반화되면서 프로그래밍 환경도 점차 중요한 개념을 언어 안으로 숨기고 사용자에겐 그것을 간편히 다룰 수 있는 인터페이스만 제공하는 추세로 흘러가고 있는데, 이런 방식은 일반적인 상황에서 생산성을 높이기는 좋지만 특정한 상황에서 속도를 높이기는 어렵다.
일반적으로 만들려면 필연적으로 많은 상황을 처리할 수 있도록 강력하고 복잡하게 만들어야 하기 때문이다.
따라서 특정 목적이 필요할 경우 언어에서 쌓은 추상화의 장벽을 뚫고 하위(low level) 개념을 이용할 필요가 있다.
아마도 이것이 어째서 메모리 관리를 알아서 해 주는 Java를 하면서 메모리 관리를 알아야 하고, Java/C++를 하면서 C를 알아야 하고, C를 하면서 하드웨어 아키텍처를 알아야 하는지에 대한 답일 것이다.
파일에 출력하기 예제
#include <fstream>
#include <iostream>
using namespase std
int main()
{
ofstream fout("sample1.txt");
if(!fout) {
cout << "파일을 열 수 없습니다.\n";
}
else {
cout << "파일을 열었습니다.\n";
fout << "hello?\n";
fout << "goodby!\n";
cout << "sample1.txt파일에다가 기록했습니다.\n";
fout.close();
cout << "파일을 닫았습니다.\n";
return 0;
}
실행:
파일을 열었습니다.
파일에다가 기록했습니다.
파일을 닫았습니다.
그리고 미리 준비한 파일을 열어보면 hello?
goodby! 라고 적혀 있다.