2010-01-30 3 views
4

파생 된 개체에 기본 개체를 할당하는 방법에 대해 C++에 대한 질문이 있습니까? 또는 Base 객체에 대한 포인터를 Derived 객체에 대한 포인터에 할당하는 방법은 무엇입니까?파생 된 개체에 기본 개체를 할당하는 방법

아래 코드에서 두 줄이 잘못되었습니다. 어떻게 수정해야합니까?

#include <iostream> 
using namespace std; 
class A{ 
public: 
    int a; 
}; 

class B:public A{ 
public: 
    int b; 
}; 

int main(){ 
    A a; 
    B b; 
    b = a; //what happend? 
    cout << b.b << endl; 

    B* b2; 
    b2 = &a;  // what happened? 
    cout << b->b << endl; 
} 

답변

2

개체가 스택에 있으면 실제로 같은 유형의 개체 만 서로 할당 할 수 있습니다. 오버로드 된 캐스트 연산자 또는 오버로드 된 할당 연산자를 통해 변환 될 수 있지만 그 시점에서 변환을 지정하고 있습니다. 컴파일러는 이러한 변환 자체를 수행 할 수 없습니다.

A a; 
B b; 
b = a; 

이 경우 A를 B에 할당하려하지만 A는 B가 아니므로 작동하지 않습니다.

A a; 
B b; 
a = b; 

패션 이후에는 효과가 있지만 예상대로되지는 않을 것입니다. 방금 B를 슬라이스했습니다. B가 A이므로 할당이 발생할 수 있지만 스택에 있기 때문에 A의 일부인 b의 부분을 a에 할당하려고합니다. 그래서, 당신이 얻는 것은 대답입니다.B에서 할당 한 사실에도 불구하고 B가 아닙니다.

실제로 한 유형의 객체를 다른 객체에 할당하려면 포인터 여야합니다.

A* pa = NULL; 
B* pb = new B; 
pa = pb; 

이것은 작동합니다. pa는 이제 pb를 가리 킵니다. 따라서 여전히 B입니다. A와 B의 가상 함수를 재정의하면 pa로 호출하면 B 버전이 호출됩니다 (가상이 아닌 함수는 여전히 A 버전을 호출합니다).).

A* pa = new A; 
B* pb = pa; 

이것은 작동하지 않습니다. PA는 B를 가리 키지 않는, 그래서 B는 A가 B를

A a; 
B* pb = &a; 

이 아무튼에게보다 의미하지 않는 A는 그냥 있기 때문에 당신은이 B로 지정해야하는 PB을 할당 할 수 없습니다 이전과 같은 이유로 일하지 않습니다. 이번에는 A가 스택 대신 힙 대신에 사용됩니다.

A* pa; 
B b; 
pa = &b; 

이것은 작동합니다. b는 A 인 B이므로 A가 가리킬 수 있습니다. 가상 함수는 B 버전을 호출하고 비 가상 함수는 A 버전을 호출합니다.

그래서, 기본적으로, A *는 B 그것이 B.

1
b = a; //what happend? 

이 일반입니다 불법 - 당신이 그것을 할 수 없도록 A는, B되지 않습니다.

b2 = &a;  // what happened? 

여기에 동일합니다.

어느 경우에도 컴파일러는 int b에 할당 할 항목을 알지 못하므로 사용자가이를 수행하지 못하게합니다. Base가 Derived의 하위 집합이기 때문에 다른 방법으로 (Derived를 Base에 할당) 작동합니다.

이제 정확히 무엇을 달성하기를 원한다면 우리가 도와 줄 수 있습니다.

가 파생 된 유형을 것으로 알려져하는 A를 할당하는 경우가 있다면, 당신은 캐스트 할 수 있습니다

A* a = new B(); 
B* b = dynamic_cast<B>(a); 

그냥 a가 아닌 경우 B 다음 dynamic_cast는이 NULL을 반환 기억을. 이 방법은 이유로 포인터 에서만 작동합니다.

+0

또한 경우에 예외를 던지고, 참고 문헌에서 작동하지 않기 때문에 A가 B 형 *는 A를 가리킬 수 없습니다 때문에의를 B 지점 수 실패. 그러나 dynamic_cast에는 가상 메소드가 필요합니다 (예 : A에 가상 소멸자 추가). – UncleBens

4

파생 된 포인터 (또는 파생 된 포인터에 대한 기본 포인터)에 기본 객체를 할당하는 것은 의미가 없기 때문에 C++이 최선을 다해 그 작업을 중단합니다. p는 실제로 기지에서 지적 경우, 포인터 d는 NULL을 포함 할 것이다이 경우

base * p = new derived; 
derived * d = dynamic_cast <derived *>(p); 

: 기본 포인터가 정말 동적 캐스트를 사용할 수있는 경우, 파생를 가리키는 경우는 예외입니다.

+0

그러나 클래스에 가상 함수가 포함되어 있지 않으면 dynamic_cast가 허용되지 않습니다. static_cast를 사용할 수는 있지만, 이는 당신이 전적인 책임을지는 것을 의미합니다. – UncleBens

+0

@UncleBens 기본 클래스에 가상 함수가 포함되어 있지 않으면 왜 파생시키는 지 묻는 것이 좋습니다. 파생시키기 위해 사용하려는 경우 가상 소멸자를 포함해야합니다. –

+0

실제로 상속 데이터에 대한 상속은 의심 스럽습니다. 이 경우에는 B를 A 멤버에게주고 A를 사용하는 생성자를 제공하여 상속하지 말 것을 제안합니다. 그런 다음 생성자를 사용하여 "캐스팅"할 수 있습니다. – UncleBens

2

컴파일러는 그런 종류의 것을 허용하지 않을 것입니다. 그리고 캐스팅 해킹을 통해이를 수행 할지라도 그렇게하는 것은 의미가 없습니다. 기본 객체의 포인터에 파생 객체를 할당하는 것은 기본 객체가 할 수있는 모든 작업을 수행 할 수 있기 때문에 의미가 있습니다. 그러나 반대의 경우가 허용되면 기본 객체에서 파생 된에 정의 된 멤버에 액세스하려고하면 어떻게됩니까? 가비지 또는 관련성이없는 데이터로 가득 찬 메모리 영역에 액세스하려고합니다.

0

파생 된 개체는 Base 개체의 일종으로, 다른 방법은 아닙니다.

관련 문제