C ++에 기본 클래스가없는 이유는 무엇입니까?
빠른 질문 : 디자인 관점에서 볼 때, 왜 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;
};
Then, instead of calling methods on the object itself, you'd be calling methods in its wrapper. This not only allows more generic programming: it also lets you separate concerns (since ideally, your object should be more concerned about what it should do, than how its memory should be managed in different situations).
Lastly, in a language that has both primitives and actual objects like C++, the benefits of having a base-class (a consistent interface for every value) are lost, since then you have certain values which cannot conform to that interface. In order to use primitives in that sort of a situation, you need to lift them into objects (if your compiler won't do it automatically). This creates a lot of complication.
So, the short answer to your question: C++ doesn't have a base-class because, having parametric polymorphism through templates, it doesn't need to.
The dominant paradigm for C++ variables is pass-by-value, not pass-by-ref. Forcing everything to be derived from a root Object
would make passing them by value an error ipse facto.
(Because accepting an Object by value as parameter, would by definition slice it and remove its soul).
This is unwelcome. C++ makes you think about whether you wanted value or reference semantics, giving you the choice. This is a big thing in performance computing.
The problem is that there IS such a type in C++! It is void
. :-) Any pointer may be safely implicitly cast to void *
, including pointers to basic types, classes with no virtual table and classes with virtual table.
Since it should be compatible with all those categories of objects, void
itself can not contain virtual methods. Without virtual functions and RTTI, no useful information on type can be obtained from void
(it matches EVERY type, so can tell only things that are true for EVERY type), but virtual functions and RTTI would make simple types very ineffective and stop C++ from being a language suitable for low-level programming with direct memory access etc.
So, there is such type. It just provides very minimalistic (in fact, empty) interface due to low-level nature of the language. :-)
C++ is a strongly typed language. Yet it is puzzling that it does not have a universal object type in the context of template specialization.
Take, for example, the pattern
template <class T> class Hook;
template <class ReturnType, class ... ArgTypes>
class Hook<ReturnType (ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
which can be instantiated as
Hook<decltype(some_function)> ...;
Now let's assume that we want the same for a particular function. Like
template <auto fallback> class Hook;
template <auto fallback, class ReturnType, class ... ArgTypes>
class Hook<ReturnType fallback(ArgTypes...)>
{
...
ReturnType operator () (ArgTypes... args) { ... }
};
with the specialized instantiation
Hook<some_function> ...
But alas, even though class T can stand in for any type (class or not) before specialization, there is no equivalent auto fallback
(I am using that syntax as the most obvious generic non-type one in this context) that could stand in for any non-type template argument before specialization.
So in general this pattern does not transfer from type template arguments to non-type template arguments.
Like with a lot of corners in the C++ language, the answer is likely "no committee member thought of it".
C++ was initially called "C with classes". It is a progression of the C language, unlike some other more modern things like C#. And you can not see C++ as a language, but as a foundation of languages (Yes, I am remembering the Scott Meyers book Effective C++).
C itself is a mix of languages, the C programming language and its preprocessor.
C++ adds another mix:
the class/objects approach
templates
the STL
I personally don't like some stuff that come directly from C to C++. One example is the enum feature. The way C# allows the developer to use it is way better: it limits the enum in its own scope, it has a Count property and it is easily iterable.
As C++ wanted to be retrocompatible with C, the designer was very permissive to allow the C language to enter in its whole to C++ (there are some subtle differences, but I do not remember any thing that you could do using a C compiler that you could not do using a C++ compiler).
참고URL : https://stackoverflow.com/questions/5697328/why-is-there-no-base-class-in-c
'program story' 카테고리의 다른 글
공식 JavaScript 참조가없는 이유는 무엇입니까? (0) | 2020.09.22 |
---|---|
Actionscript 3을 사용하여 ByteArray 언로드 (0) | 2020.09.22 |
Node.js 라이브러리 Winston을 사용하여 로그에 타임 스탬프를 추가하려면 어떻게해야합니까? (0) | 2020.09.21 |
이해하기 쉬운 설명으로 Java에서 실행 가능이란 무엇입니까? (0) | 2020.09.21 |
할당 된 메모리에서 free ()를 사용하지 * 않아도 * 괜찮습니까? (0) | 2020.09.21 |