2011-08-17 6 views
0
class A 
{ 
public: 
    A(int i):pi(&i){} 
    int* func() 
    { 
    //dosomething 
    return pi; 
    } 
private: 
    int*pi; 
}; 

class B:public A 
{ 
    A*pa; 
public: 
    int* bar() 
    { 
     //dosomething 
     return pa->func(); 
    } 
}; 

int main() 
{ 
    A*pa=new B(); 
    int*pi=pa->bar(); 
    delete pa; 
    return 0; 
} 

내 위의 수업 (더 나은보기를 위해 작게 줄였습니다)을 입력하면 도움이 될만한 사람이 있습니까? 나는 잘못된 선택을 조금 걱정한다.상속 및 포인터 사용 - 올바른 사용을위한 조언

+0

'클래스 A'가상 소멸자는 어디에서 발생 했습니까? – sharptooth

+0

대답이 불가능합니다. 너 뭐하려고? –

+1

좋은 C++ 책을 준비하고 시작하는 것이 좋습니다. 당신은 명확하게 * 상속 *의 개념을 이해하지 못합니다! – Nim

답변

-2

게시 한 코드가 잘못되어 혼란 스럽습니다.

A*pa=new B(); 
    int*pi=pa->bar(); 

Thats not that! A에는 bar() 함수가 없습니다. B 객체 만 만들면 A로 캐스팅됩니다 (실제로는 누락 된 것).

정확히 무엇을하고 싶은지 확실하지 않지만 인터페이스와 비슷한 것으로 생각됩니다. 인터페이스는 다음과 같이 작동합니다. (순수한) 가상 함수 집합을 정의하는 추상 기본 클래스가 있으며 "loadData, saveData"등의 고정 된 기능 집합을 설명하지만이 기능을 구현하는 방법은 설명하지 않습니다. 당신은 실제로 XML 파일에 데이터를 저장하거나 등 평면 바이너리로 (참고 : 하나는 그것을 위해 스트림을 사용하지만, 내 경우에는 내가 예제로 사용) 할 수

class YourInterface { 
public: 
    YourInterface(){ 
    } 

    virtual ~YourInterface(){ 
    } 

    virtual void saveData(Data data) = 0; //Pure virtual = Childs are forced to implement those functions to become non abstract 
    virtual Data loadData() = 0; 
}; 

//One implementation to load and save data to/from a xml file 
class XmlImplementation : public YourInterface { 
public: 
    XmlImplementation(){ 
    } 

    virtual ~XmlImplementation(){ 
    } 

    //Overriding functions: 
    void saveData(Data data){ 
     //Save data to a xml file here 
    } 

    Data loadData(){ 
     //Load data from a xml file here 
    } 
}; 

void main(){ 
    YourInterface* p; 
    p = (YourInterface*) new XmlImplementation(); 

    p->loadData(); //We just want to get our Data here, we dont care whether its from a xml or binary file etc. 
} 

참고 :에 대한 죄송합니다 끝나지 않은 게시물 나는 우연히 버튼을 누르십시오.

+0

기본 클래스 포인터로의 캐스트는 암시 적이므로 캐스트가 누락되지 않았습니다. 반면에 C 스타일의 캐스트를 사용합니다. ** 특히 C++에 대해 누군가를 가르치려고 할 때 C++ **에서는 절대하지 말아야합니다. 문제는'p = (YourInterface *) new int (42)'가 자동으로 컴파일되지만 격렬히 부정확하다는 것입니다. base에 캐스트하면, 서브 클래스에 캐스트하면,'static_cast' 또는'dynamic_cast'를 부수적으로 사용합니다. –

+0

그때 미안해, 마지막으로 내가 캐스팅하지 못했던 문제가 있다는 것을 기억했다. – Paranaix

+0

문제가 있다면 다른 문제가 있기 때문입니다. 잘 설계된 C++ 코드는 "함수 스타일" "캐스트"(실제로는 임시 인스턴스를 생성하라는 요청)를 제외하고는 캐스트를 필요로하지 않아야합니다. –

0

코드에 몇 가지 문제점이 있습니다. 다음은 그 중 일부입니다 :

A(int i):pi(&i){} 

값으로 전달되는 인수의 주소를 취합니다. i은 A의 생성자가 반환 할 때 더 이상 존재하지 않습니다.

A*pa; 

B::pa은 초기화되지 않습니다.

delete pa; 

제대로 작동하려면 A에 가상 소멸자를 추가해야합니다.

+0

'delete'는 문제입니다. B 클래스의 시작 전에 오프셋이 없다는 보장은 없습니다. –

+0

@Let_Me_Be : A는 가상 소멸자가 없기 때문에 문제가됩니다. 그 이유는 A가 B에서 오프셋에서 시작될 수 있기 때문에 컴파일러는 포인터가 유형 A이면 실제 A의 실제 시작을 가리키고 가상 소멸자는 B의 시작을 올바르게 찾지 못하도록하기 때문입니다. –

+0

@ 클래스가 다형성 일 경우, 삭제는 올바르게 올바른 포인터를 해제합니다. 가상 소멸자가 꼭 필요한 것은 아니며,이 문제를 예방할 수있는 개인용 비 가상 소멸자가있을 수 있습니다. –

1

코드에 몇 가지 문제가 있습니다. 첫째는이 파라미터 i를 가리 키도록 설정 부재 pi 여기

A(int i):pi(&i){} 

이다. 그러나 i은 생성자가 완료 되 자마자 사라집니다. 이제 아무 것도 가리 키지 않는 포인터가 있습니다!

클래스 B는 모든 사용자 정의 생성자가없는 여기

class B:public A 
{ 
    A*pa; 

비슷한 문제. 즉, pa은 아무데도 가리 키도록 설정되지 않습니다. 기본 클래스에 포인터를 통해 개체를 삭제하는 경우

세 번째 문제는 기본 클래스는 가상 소멸자가있는 경우에만 작동

A*pa=new B(); 
// ... 
delete pa; 

주요

입니다.

코드를 컴파일하려고하면 생성자에 몇 가지 추가 문제가 있습니다.

관련 문제