빠른 질문 : 디자인 관점에서 볼 때, 왜 C ++에는 마더 오브 올베이스 클래스가 없는데, 보통 object
다른 언어로는 무엇입니까?
답변
최종 판결은 Stroustrup의 FAQ 에서 찾을 수 있습니다. 요컨대 의미 론적 의미를 전달하지 않습니다. 비용이 발생합니다. 템플릿은 컨테이너에 더 유용합니다.
C ++에 유니버설 클래스 Object가없는 이유는 무엇입니까?
우리는 하나가 필요하지 않습니다. 제네릭 프로그래밍은 대부분의 경우 정적으로 형식이 안전한 대안을 제공합니다. 다른 경우는 다중 상속을 사용하여 처리됩니다.
유용한 유니버설 클래스는 없습니다. 진정한 유니버설은 그 자체의 의미를 가지고 있지 않습니다.
“범용”클래스는 유형과 인터페이스에 대한 엉성한 사고를 장려하고 과도한 런타임 검사로 이어집니다.
범용 기본 클래스를 사용하는 것은 비용을 의미합니다. 객체는 다형성이되도록 힙 할당되어야합니다. 이는 메모리 및 액세스 비용을 의미합니다. 힙 개체는 자연스럽게 복사 의미 체계를 지원하지 않습니다. 힙 개체는 리소스 관리를 복잡하게하는 단순 범위 동작을 지원하지 않습니다. 범용 기본 클래스는 dynamic_cast 및 기타 런타임 검사 사용을 권장합니다.
답변
우선 왜베이스 클래스를 원하는지 생각해 봅시다. 몇 가지 다른 이유를 생각할 수 있습니다.
- 모든 유형의 개체에서 작동하는 일반 작업 또는 컬렉션을 지원합니다.
- 모든 개체에 공통적 인 다양한 절차를 포함합니다 (예 : 메모리 관리).
- 모든 것이 객체입니다 (프리미티브가 아닙니다!). Objective-C와 같은 일부 언어에는이 기능이 없기 때문에 상황이 매우 복잡해집니다.
이것이 Smalltalk, Ruby 및 Objective-C 브랜드의 언어가 기본 클래스를 갖는 두 가지 좋은 이유입니다 (기술적으로 Objective-C에는 실제로 기본 클래스가 없지만 모든 의도와 목적에 따라 그렇습니다).
# 1의 경우, C ++에 템플릿을 포함하여 모든 개체를 단일 인터페이스로 통합하는 기본 클래스가 필요하지 않습니다. 예를 들면 :
void somethingGeneric(Base);
Derived object;
somethingGeneric(object);
파라 메트릭 다형성을 통해 유형 무결성을 완전히 유지할 수 있다면 불필요합니다!
template <class T>
void somethingGeneric(T);
Derived object;
somethingGeneric(object);
# 2의 경우 Objective-C에서는 메모리 관리 절차가 클래스 구현의 일부이고 기본 클래스에서 상속되는 반면 C ++의 메모리 관리는 상속이 아닌 구성을 사용하여 수행됩니다. 예를 들어 모든 유형의 객체에 대한 참조 계산을 수행하는 스마트 포인터 래퍼를 정의 할 수 있습니다.
template <class T>
struct refcounted
{
refcounted(T* object) : _object(object), _count(0) {}
T* operator->() { return _object; }
operator T*() { return _object; }
void retain() { ++_count; }
void release()
{
if (--_count == 0) { delete _object; }
}
private:
T* _object;
int _count;
};
그런 다음 개체 자체에서 메서드를 호출하는 대신 래퍼에서 메서드를 호출합니다. 이것은보다 일반적인 프로그래밍을 허용 할뿐만 아니라 관심사를 분리 할 수도 있습니다 (이상적으로는 객체가 다른 상황에서 메모리를 관리하는 방법보다 수행해야하는 작업에 더 관심을 가져야하기 때문에).
마지막으로, C ++와 같은 기본 객체와 실제 객체를 모두 포함하는 언어에서는 기본 클래스 ( 모든 값에 대한 일관된 인터페이스)를 갖는 이점 이 손실됩니다. 그러면 해당 인터페이스를 준수 할 수없는 특정 값이 있기 때문입니다. 이런 상황에서 프리미티브를 사용하기 위해서는 그것들을 객체로 들어 올려야합니다 (컴파일러가 자동으로하지 않는다면). 이것은 많은 합병증을 만듭니다.
따라서 귀하의 질문에 대한 짧은 대답은 C ++에는 기본 클래스가 없습니다. 왜냐하면 템플릿을 통한 매개 변수 다형성을 가지므로 그럴 필요가 없기 때문입니다.
답변
C ++ 변수의 지배적 인 패러다임은 참조에 의한 전달이 아니라 값에 의한 전달입니다. 모든 것이 루트에서 파생되도록 강제 Object
하면 값으로 전달하는 것은 사실 오류가됩니다.
(값으로 Object를 매개 변수로 받아들이 기 때문에 정의에 따라 슬라이스하고 영혼을 제거합니다).
이것은 반갑지 않습니다. C ++를 사용하면 값 또는 참조 의미론을 원하는지 여부를 생각하여 선택할 수 있습니다. 이것은 성능 컴퓨팅에서 중요한 부분입니다.
답변
문제는 C ++에 이러한 유형이 있다는 것입니다! 입니다 void
. 🙂 void *
기본 유형에 대한 포인터, 가상 테이블이없는 클래스 및 가상 테이블이있는 클래스를 포함하여 모든 포인터를으로 안전하게 캐스트 할 수 있습니다 .
모든 범주의 객체와 호환되어야하므로 void
가상 메서드를 포함 할 수 없습니다. 가상 함수와 RTTI가 없으면 유형에 대한 유용한 정보를 얻을 수 없지만 void
(모든 유형과 일치하므로 모든 유형에 맞는 것만 알 수 있음), 가상 함수와 RTTI는 단순한 유형을 매우 비효율적으로 만들고 C ++가 존재하지 않도록합니다. 직접 메모리 액세스 등의 저수준 프로그래밍에 적합한 언어
그래서 그런 유형이 있습니다. 언어의 저수준 특성으로 인해 매우 최소한의 (사실 빈) 인터페이스를 제공합니다. 🙂
답변
C ++는 강력한 형식의 언어입니다. 그러나 템플릿 전문화의 맥락에서 범용 객체 유형이 없다는 것은 당혹 스럽습니다.
예를 들어, 패턴
template <class T> class Hook;
template <class ReturnType, class ... ArgTypes>
class Hook<ReturnType (ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
다음과 같이 인스턴스화 될 수 있습니다.
Hook<decltype(some_function)> ...;
이제 특정 함수에 대해 동일한 것을 원한다고 가정 해 봅시다. 처럼
template <auto fallback> class Hook;
template <auto fallback, class ReturnType, class ... ArgTypes>
class Hook<ReturnType fallback(ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
전문화 된 인스턴스화
Hook<some_function> ...
그러나 아아, 클래스 T가 전문화 전에 어떤 유형 (클래스이든 auto fallback
아니든)을 나타낼 수 있지만, 어떤 것을 의미 할 수있는 동등한 것은 없습니다 (이 컨텍스트에서 가장 명백한 일반 비 유형 유형으로 해당 구문을 사용하고 있습니다). 전문화 전 비 유형 템플릿 인수.
따라서 일반적으로이 패턴은 형식 템플릿 인수에서 형식이 아닌 템플릿 인수로 전송되지 않습니다.
C ++ 언어의 많은 구석과 마찬가지로 대답은 “위원회 구성원이 생각하지 않은 것”일 것입니다.
답변
C ++는 처음에 “C with classes”라고 불 렸습니다. C #과 같은 다른 현대적인 것과는 달리 C 언어의 발전입니다. 그리고 C ++를 언어로 볼 수는 없지만 언어의 기초로 볼 수 있습니다 (예, Scott Meyers의 저서 Effective C ++를 기억하고 있습니다).
C 자체는 언어, C 프로그래밍 언어 및 전 처리기의 혼합입니다.
C ++는 또 다른 조합을 추가합니다.
-
클래스 / 객체 접근 방식
-
템플릿
-
STL
저는 개인적으로 C에서 C ++로 직접 오는 것을 좋아하지 않습니다. 한 가지 예는 열거 형 기능입니다. C #을 통해 개발자가 사용할 수있는 방법이 훨씬 더 좋습니다. 자체 범위에서 열거 형을 제한하고 Count 속성이 있으며 쉽게 반복 할 수 있습니다.
C ++가 C와 역 호환되기를 원했기 때문에 디자이너는 C 언어가 전체적으로 C ++에 들어가도록 허용하는 것이 매우 관대했습니다 (미묘한 차이가 있지만 C 컴파일러를 사용하여 수행 할 수있는 작업은 C ++ 컴파일러를 사용할 수 없습니다).