2014-01-12 2 views
0

첫째 :기본 복사 생성자에 대한 명시 적 호출 => RTTI 정보가 손실되었습니다. 곤충? 모든

나는 정말 일이 일어나고 무엇을 이해하기 위해, 단지 호기심이 질문을 부탁드립니다. 이런 프로덕션 코드에서는 사용하지 않습니다. 다른 해결책을 제안하는 답변을보고 싶습니다. 그 메모리 영역에 대한 참조가 손실되기 때문에

class Base{ 
public: 
    virtual void copy(){} 
}; 

class Derived: public Base{ 
public: 
    void copy(){ 
     Base a1; 
     this->Base::Base(a1);//explicit call to base copy constructor 
    } 
}; 

나는 어떤 경우에는 복사 생성자를 명시 적으로 호출 좋지 않은 것을 알고 (클래스 멤버가 동적으로 할당 한 경우, :.

이 코드를 갖는 그리고 더 이상 해방되지 않을 것이다).

아래 예제에서 기본 복사 생성자를 호출 할 때 직접적인 문제는 없습니다. 첫눈에 나는 copy() 메서드가 호출 될 때 기본 하위 개체를 다시 초기화해야한다고 생각합니다.

int main(){ 
    Base** _a = new Base*; 
    _a[0] = new Derived(10); 
    Derived* b = dynamic_cast<Derived*>(_a[0]); 
    assert(b);//<===true 
    _a[0]->copy(); 
    //t is still available and can be accessed through b 
    std::cout<<b->t;//correct: 10 
    b = (Derived*)_a[0]; 
    std::cout<<b->t;//correct: 10 
    b = dynamic_cast<Derived*>(_a[0]); 
    assert(b);//<===false  
} 

그러나 두 번째 어설 션은 실패합니다. 누군가이 행동을 설명 할 수 있습니까? 왜 이런 일이 일어나는 걸까요? 기본 복사 생성자를 호출 할 때 typeid가 손실 되었습니까?

나는 Visual Studio를 사용하여 코드를 컴파일 2012 클래스 멤버 초기화 클래스의 가상 함수 테이블에 vptr에서 포인터를 설정 생성자 전에

+2

이 코드는 컴파일도 안가 ... –

+0

@KerrekSB 나도 컴파일 exect하지 않았다 그러나 나는 시도하고 있었다 몇 가지 물건과 나는 그것을 컴파일하고 내가 무슨 일이 일어 났는지 알고 싶었 실현. –

+0

멤버 함수에 대한 포인터와 동일하기 때문에 컴파일됩니다. A :: * t로 전화 할 수 있습니다 (this -> * t)() –

답변

3

. 부모 클래스의 생성자를 수동으로 호출하면 파생 클래스 vptr이 부모 클래스의 vtable을 가리 킵니다.

+0

이것은 실현 가능합니다. –

+0

흥미 롭다. 나는 __vfptr이 실제로 변경되었는지 확인했다. –

1

글쎄, Base::Base(const Base&)을 호출 할 때 Derived 유형의 개체에 할당 된 메모리에 Base 유형의 새 개체를 생성하게됩니다. 그 후에 모든 가상 함수는 예를 들어 Base:: 구현을 가리 킵니다.

개체를 다시 초기화하려는 경우 파생 형식 Derived::Derived(const Derived&)의 생성자를 호출해야합니다.이 개체의 일부만 다시 초기화 할 수는 없습니다. 이외에도

: 먼저 오브젝트 파괴한다에 의해를 정정 reinitializetion을 할 수
:

this->~Derived(); //cleanly destruct the object 
this->Derived::Derived(...); //rebuilt the object in place 
관련 문제