기본 클래스 포인터는 파생 클래스 개체를 가리킬 수 있습니다. 그 반대가 사실이 아닌 이유는 무엇입니까?
기본 클래스 포인터는 파생 클래스 개체를 가리킬 수 있습니다. 캐스팅하지 않고 그 반대가 아닌 이유는 무엇입니까? 논리적으로 기본 클래스에는 파생 클래스에 대한 정보가 충분하지 않지만 파생 클래스에는 기본 클래스의 정보도 있어야합니다. 여기에 몇 가지 기본 사항이 없습니다.
내가 개가 있다고 말하면 내가 애완 동물이 있다고 안전하게 가정 할 수 있습니다.
내가 애완 동물이 있다고 말하면 그 동물이 개인 지, 고양이인지 기린인지 알 수 없습니다. 추가 정보를 모르면 내가 개가 있다고 가정 할 수 없습니다.
유사하게 파생 개체는 기본 클래스 개체 (하위 클래스이므로)이므로 기본 클래스 포인터로 가리킬 수 있습니다. 그러나 기본 클래스 개체는 파생 클래스 개체가 아니므로 파생 클래스 포인터에 할당 할 수 없습니다.
(지금 들리는 삐걱 거리는 소리는 스트레칭의 비유입니다)
이제 내 애완 동물을위한 선물을 사고 싶다고 가정 해 보겠습니다.
첫 번째 시나리오에서 당신은 그것이 개라는 것을 알고 있습니다. 당신은 나에게 가죽 끈을 살 수 있습니다. 모두가 행복합니다.
두 번째 시나리오에서 나는 내 애완 동물이 뭔지 말하지 않았기 때문에 어쨌든 나에게 선물을 사려면 내가 말하지 않은 정보를 알아야한다 (또는 추측 만하면된다). 정말 개를 키웠는데 모두가 행복합니다.
그러나 내가 실제로 고양이를 가졌다면 이제 우리는 당신이 나쁜 가정 (캐스트)을했고 불행한 고양이가 가죽 끈에 있다는 것을 알고 있습니다 (런타임 오류).
두 개의 개체가 있습니다.
class A {
int a;
};
class B : A {
int b;
};
의 인스턴스를 할당합니다 B
. 우리는 그것으로 A*
또는 B*
.
의 인스턴스를 할당합니다 A
. 캐스트 B*
하려면 멤버에게 할당 된 공간이 있어야 b
합니까?
어, 기본 클래스가 파생 클래스가 아니기 때문입니다.
유형에 대한 유효한 포인터가 있으면 가리키는 개체가 특정 위치에 특정 데이터를 가지고 있으므로 찾을 수 있다는 것입니다. 파생 된 개체에 대한 포인터가있는 경우 가리키는 개체에 Derived의 모든 데이터 멤버가 포함되어 있음을 보장합니다. 그러나 Base를 가리키는 경우 실제로는 해당 개체가없고 Bad Things Happen ™이 있습니다.
그러나 Derived는 모든 Base 데이터 멤버가 동일한 위치에 있음을 보장합니다. 이것이 Base에 대한 포인터가 실제로 Derived를 가리킬 수있는 이유입니다.
파생 클래스에는 기본 클래스에있는 모든 것이 포함되기 때문입니다. 그러나 기본 클래스에는 파생 클래스에있는 모든 것이 포함되지 않습니다.
기본 클래스를 파생 클래스로 형식 캐스팅하는 것은 권장되지 않습니다. 기본 클래스의 일부가 아닌 멤버에 액세스하려고하면 어떻게됩니까?
호랑이는 동물이기 때문에 유효합니다.
Animal * pAnimal = new Tiger();
대상이 독 다트 개구리라는 것이 사실이 아니기 때문에 이것은 유효하지 않습니다.
PoisonDartFrog * pPoisonDartFrog = new GenericFrog();
C ++는 정적으로 형식화 된 언어이기 때문에 암시 적 Base-to-Derived 변환을 허용하면 형식 시스템이 손상됩니다. Bjarne Stroustrup은 "메시지를 이해할 수 없음"런타임 오류를 원하지 않았습니다.
class Base
{
public:
int a;
}
class Derived : public Base
{
public:
float b;
}
Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base
// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
// points to the SAME DATA as pBase
짧은 대답
class A{
public:
method1();
};
class B: public A{
public:
method2();
};
int main(){
// Case 1
A* ptr_base = new B();
// Here I can call all the methods in A by ptr_base even though it is assigned B ...
// ... because B is derived from A and has all the information about methods of A
// Case 2
B* ptr_derived = new A(); // this will cause error
// Now here ptr_derived is assigned information of A ...
// ... So with this information can I call (*ptr_derived).method2(); ?...
// ... the answer is No because A does not have information of method2() ...;
// ... thus this declaration loses its meaning and hence error.
return 0;
}
기본 클래스 포인터는 기본 클래스 또는 파생 형식의 인스턴스를 가리킬 수 있기 때문입니다. 파생 된 포인터는 파생 된 유형 또는 그 하위 클래스 만 가리킬 수 있습니다.
struct Base {};
struct Derived : Base {};
struct Derived2 : Base {};
Base* p = new Derived(); //Fine, Derived inherits from Base
Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived.
Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived.
As far as the why goes: In general the base pointer is more general than the derived pointer. As such it knows less about the inherited type. A derived pointer cannot be assigned a pointer to a base type without casting simply because it cannot tell if the base pointer is of the Derived type or one of its children.
If assign an address from a base class pointer into a derived class pointer, you can potentially assign a base class object to a derived class pointer. You run the risk of accessing derived class members when you don't have a derived class. Whereas derived class methods would work on a base class, they would only do so if the method didn't access derived class member data.
That's a huge risk.
So we force you to cast so that you have to acknowledge the disclaimer that says (you may make a stupid mistake, please be careful).
In general , a pointer of one type cannot point to an object of a different type. However, there is an important exception to this rule that relates only yo derived classes. In this situation a pointer of type BASE* may point to an object of type Derived, i.e a base class pointer can point to a derived class object but vice versa is not true as the base object is not it's sub class object.
This is because, "the type of a pointer is the type of object the pointer points to". So,
- If we have base type pointer (*B):
then we expect a base type object (and would like to access its functionalities) at the address pointed by B, and if we get a derived type object at that address then also we are able to access the required functionalities. This is because derived type is-a base type.
- If we have derived type pointer (*D):
그런 다음 D가 가리키는 주소에서 파생 된 유형 객체를 예상하고 거기에서 기본 유형 객체를 얻으면 기본 유형이 파생 유형이 아니므로 기본 유형 객체에서 파생 된 클래스 정보에 액세스 할 수 없습니다.
'development' 카테고리의 다른 글
C ++에서 동적으로 할당 된 개체에 대한 포인터 벡터를 사용할 때 메모리 누수를 피하는 방법은 무엇입니까? (0) | 2020.11.13 |
---|---|
LINQ : 두 시퀀스에 정확히 동일한 요소가 있는지 확인 (0) | 2020.11.13 |
MYSQL-데이터베이스 선택 (0) | 2020.11.13 |
iPad 브라우저 시뮬레이터? (0) | 2020.11.12 |
MEF가 DI / IoC 컨테이너가 아닌 이유는 무엇입니까? (0) | 2020.11.12 |