문서의 임의 삭제는 제재 대상으로, 문서를 삭제하려면 삭제 토론을 진행해야 합니다. 문서 보기문서 삭제토론 C++ (문단 편집) === 객체 지향 프로그래밍 === C++는 '''[[객체 지향 프로그래밍]]'''을 지원하지만, C++의 객체지향은 다른 객체지향 언어에서와는 성격이 좀 다르다. 대다수의 객체지향 언어에서는 많은 부분을 런타임에 처리하며 메모리를 자동으로 관리해준다. C++은 기반 프레임워크가 존재하지 않아 클래스가 어떤 일급 객체가 아니라, 일반 변수처럼 메모리 덩어리일 뿐이다. 최대한 많은 것을 컴파일 타임에 처리하는 것을 지향하고 동적인 메모리 할당을 지양한다. 그리고 결정적으로 메모리 등을 프로그래머가 직접 관리하게 하기 때문에 클래스를 포함해 전반적인 프로그램 설계 자체가 상당한 차이를 보이게 된다. [[Java]] 등의 다른 객체지향 언어에서와 같은 방식으로 C++ 클래스를 디자인하면 거의 틀림없이 런타임 오류 또는 메모리 문제가 발생한다. 특히 [[가비지 컬렉션|쓰레기 수집]]을 지원하는 Java로 입문하여 C++로 갈아타는 테크를 탄 학생이라면 처음에는 메모리가 줄줄 새는 프로그램을 만들게 될 것이다. 반면 C++ 스타일을 숙지하고 다른 객체지향 언어에서 프로그래밍을 하는 경우 특별히 안 될 것은 없지만, 해당 언어의 원어민 스타일로 작성한 코드에 비해 시간이 많이 걸리고 클래스 및 프로그램 구조가 지나치게 경직되는 경향이 있다. 소멸자가 호출되지 않는 등의 차이점은 있지만 심각한 문제가 되는 경우는 많지 않다. 이러한 차이가 생기는 것은 대부분의 객체지향 언어는 직접적으로 [[Smalltalk]]의 영향을 받은 반면, C++는 Smalltalk보다 먼저 객체지향의 초보적인 개념을 제시한 시뮬레이션 전용 언어인 [[Simula]]에서 직접 영향을 받았기 때문이다. [* Smalltalk에서는 모든 클래스는 최상위 클래스를 상속받으며, 클래스가 가진 모든 [[메타]] 정보를 어디에서나 접근할 수 있다. Smalltalk의 클래스는 편의상 자료형으로 취급되지만 사실 클래스도 어떤 객체로부터 생성되는 인스턴스다. 클래스에 대해 메타 정보를 서술하는 메타클래스가 존재하며, 이를 외부 인터페이스로 내보이는 Reflection을 구현한다. 즉 Smalltalk의 클래스는 네이티브하게 런타임 인스턴스의 속성만 정의해놓은 것이 아니라, 클래스도 {{{new GameObject}}} 마냥 생성되는 인스턴스일 뿐이다.] 이는 C 프로그램과의 호환성을 고려한 결과이기도 하지만, 기본적으로 C++에서 프로그램의 성능을 희생시키지 않기 위해서였다. Smalltalk의 경우 당시의 기술적 한계도 있고 해서 C보다 대체로 수십 배 정도 느렸고, 이는 당시 C++에서 지향하는 결과가 아니었기 때문이다. 이런 차이 때문에 Java, C# 등의 언어를 먼저 접한 프로그래머들은 C++의 객체지향이 짝퉁이라며 싫어하기도 한다. 하지만 순수 객체지향 프로그래밍 언어임을 전면에 내세우는 Java나 C#과 달리, 객체지향 패러다임'''도''' 지원하는 다중 패러다임 언어인 C++ 입장에서는 얼마나 순수하게 객체지향의 이상을 잘 따르는가보다, C++가 제공하는 온갖 패러다임까지 아우르는 내적 일관성이 더 중요하므로 해당 언어들과 C++를 동일선상에 놓고 비교할 수는 없다. 대표적인 예시로 인자로 전달하는 값은 기본적으로 복사되는 것, 함수 내부에서 객체를 동적으로 생성해서 그 객체의 포인터를 반환하는 것이 있다. C++에서는 메모리 문제를 일으키기 쉬운 방식이라서 설계 단계부터 이런 동작을 배제해야할 필요가 있다. 거의 대부분의 프로그램은 실행되고 있는 현재 [[함수|문맥]]에서의 지역 변수를 [[스택(자료구조)|스택 영역]]에 저장하는데, 한 문맥의 실행이 완료되면 그 함수의 스택 영역 변수를 위한 메모리는 모두 삭제된다. 그리고 이 변수는 쓰레기 데이터로 남아있다가 다른 함수를 호출할 때 덮어씌워진다. 공유 자원과 같은 특정 데이터를 유지하려면 힙 영역에 할당해야 한다. 가비지 컬렉션이 자동으로 되는 언어에서는 언어 설계 차원에서 메모리에 대한 걱정을 덜기 위해 사용되지 않는 메모리를 자동으로 해제 해주기 때문에 매우 흔히 사용되는 방법이다. [* 다만 해당 언어들조차 파일 입출력에서는 별도의 소멸자, 파괴 메서드, 예외 처리의 도움이 필요하다.] 그러나 문제가 생기는 건 오래된 스타일의 C++ 코드에서나 그런 것이고, Modern C++에서는 스마트 포인터를 사용하거나 이를 이동 연산[* 원본 객체가 필요없는 경우, 새로 객체를 생성할 때 깊은 복사 없이 기존 객체의 메모리를 재활용할 수 있도록 하는 기능이다.]을 통해 그들과 완전히 같은 구조를 구현 가능하기 때문에 더 이상 해당이 없는 사항이다. 예를 들어 한 동적 객체를 여러 소유권자가 공유하는 경우 (참조 대상에 대한 횟수를 기록하는) 레퍼런스 카운팅을 지원하는 {{{std::shared_ptr}}}를, 단일 소유자만 존재하는 경우 {{{std::unique_ptr}}}를 사용한다 [* 또한 레퍼런스 카운팅으로 인해 발생하는 {{{std::shared_ptr}}}의 순환 참조 문제를 피하기 위해서 참조만 할 뿐 소유권은 지니지 않는 {{{std::weak_ptr}}}도 지원한다. {{{std::weak_ptr}}}은 객체 대신 {{{std::shared_ptr}}}을 참조한다고 보면 된다. 하나의 {{{std::shared_ptr}}}과 다수의 {{{std::weak_ptr}}}을 사용하면 여러 소유권자가 하나의 객체를 공유하면서도 순환 참조 문제를 해결할 수 있다.].저장 버튼을 클릭하면 당신이 기여한 내용을 CC-BY-NC-SA 2.0 KR으로 배포하고,기여한 문서에 대한 하이퍼링크나 URL을 이용하여 저작자 표시를 하는 것으로 충분하다는 데 동의하는 것입니다.이 동의는 철회할 수 없습니다.캡챠저장미리보기