2012-07-28 3 views
0

여기 내 첫 번째 게시물! 나는 수년간이 사이트를 참고로 사용하여 일반적인 문제에 대한 해결책을 찾고 있습니다. 불행히도 내가 직면하고있는이 문제는 아직 여기에서 발견되지 않은 문제입니다! 그래서 여기 있습니다. 나는 얼마 동안 프로젝트에서 일해왔다. 내 프로그램에는 수천 줄의 코드가 있으므로 여기에 모두 게시하지 않을 것입니다. 기본적으로 부모 클래스를 이미 내 코드에서 초기화 된 하위 클래스로 변경하려는 하위 클래스가 있습니다. 이것이 가능한지 또는 좋은 코드 연습인지 확실하지 않습니다. 그러나 나는 너희들이 그것의 재판관이되게 할 것이다! 여기에 내가 직면하고있는 문제는 다음과 같습니다C++ 하위 클래스 내의 상위 클래스 변경

이 컴파일 그렇다면
#include <stdio.h> 

class Base 

    public: 
     int data; 
     Base(int); 
}; 

class Child : public Base 
{ 
    public: 
    Child(void); 
     void run(Base*); 
}; 

Base::Base(int var) 
{ 
    data=var; 
} 


void Child::run(Base* base) 
{ 
     this = base //I know that you can create a reference to the parent class 
        //by casting this pointer to a Base pointer, but was wondering 
        //if you can do this the other way around. 
    printf("%d\n",Base::data); 
} 

int main() 
{ 
Base* base1 = new Base(5); 
Base* base2 = new Base(3); 
    Child one(); 

one.run(base1); 

    delete base1; 
    delete base2; 
    base1=0; 
    base2=0; 
    return 0; 
} 

는 5 같은 것을 outputt 것 내가 run 메소드 매개 변수를 변경할 경우 3. 같은이인가 인쇄해야 base2하는 (이되지 않습니다) 가능한? 고맙습니다!

답변

0

아니요, 그런 일은 할 수 없습니다. This은 읽기 전용 포인터입니다. 줄

this = base; 

구문 오류가 발생합니다.

C++의 기본 클래스는 정적입니다. 런타임에는 변경할 수 없습니다. 수업 (베이스와 아이 모두) 가상 함수가없는 경우

는 있지만, 때라도 작동합니다 :

(Base&)*this = *base; 

를 내가 이렇게 당신을 낙담 것이다 동시에. 낙담하는 이유는 그러한 코드가 변경에 매우 취약하기 때문입니다. 예를 들어 가상 메소드가 클래스 중 하나에 추가되면 VMT가 겹쳐 쓰입니다. 이것은 다중 상속에서 작동하지 않을 수 있습니다. MSVC 실험을 통해 클래스의 바이너리 레이아웃에서 기본 클래스의 순서가 변경되는 경우가 있음을 알게되었습니다.

즉, 인 경우 컴파일러에서 사용하는 레이아웃이 정확히 인 경우 사용할 수 있습니다. 컴파일러가 앞으로이 레이아웃을 변경하지 않을 것이라고 확신하는 경우. 그렇지 않은 경우 더 잘 피하십시오.

올바른 방법은 특수 방법을 만들고 필드별로 데이터 필드에 복사하는 것입니다.

+0

실제로 * this = * base는 Child :: operator = (const Base &) 정의. static_cast (b) = c ;, Base :: operator =를 호출 할 수 있습니다. 가상 함수의 존재 여부에 관계없이 항상 잘 정의되어 있습니다. –

+0

궁금합니다. 왜이 유형의 과제를 방해 하시겠습니까? this = * base? 나는 컴파일러 오류가있어,하지만 방금 기본 포인터로 lvalue 캐스팅하고 잘 작동합니다. 모든 데이터를 복사하거나 대입 연산자를 오버로드하는 메서드를 만들 수는 있지만 부모 클래스는 많은 양의 데이터를 가지고 있으며 매우 복잡합니다. –

+0

'* this = * base'를 정확한 코드가 아닌 개념적인 것으로서 취급하십시오. –

1

원하는 작업을 정확하게 수행 할 수는 없지만 비슷한 작업을 수행 할 수는 있습니다. 부모 클래스가 다른 인스턴스의 복사본입니다 인스턴스를 만들 수있는 복사 생성자가있는 경우, 자녀 객체가 구축되는 동안, 당신은 당신의 부모 객체를 생성하는 복사 생성자를 사용할 수 있습니다

class Child : public Base 
{ 
    public: 
    Child(const Base &b) : Base(b) { ...} 

Base 부분이 다른 Base 개체의 부분과 동일한 Child 개체가 있습니다.

0

this을 const로 간주하십시오. 기본 클래스에 대한 참조를 얻으면 간단하게 하위 클래스의 일부 하위 집합 (부분)에 대한 참조를 얻습니다. 기본 클래스 인스턴스는 class-as-a-whole (이 경우 하위 클래스 인스턴스)에 밀접하게 바인딩됩니다. 기본 클래스가 초기화되는 방법을 지시 할 수 있지만 (Ernest의 응답 참조) 링크를 끊을 수는 없습니다.|

[... :

는 보통 클래스와베이스 클래스의 메모리 레이아웃은 뭔가처럼 기본 클래스 | ... ...]]

그것은 독립적으로 존재하는 것에 반대되는 것으로서 문자 그대로 포함되어 있습니다. (다음은 정상적이지 않습니다. 나는 결코 일어나지 않을 것이라고 말합니다. 그러나 그것은 내부 컴파일러입니다. 선택 사항) :

[... | base-class에 대한 참조 | ... ...] [독립적 인 기본 클래스 인스턴스]

+0

이것은 또한 알고 매우 좋습니다! 게시 해 주셔서 감사합니다. –

관련 문제