2013-05-16 1 views
-4

아래 코드 조각은 정상적으로 작동합니다. 생성자와 소멸자포인터를 변수로 초기화해야하는 이유는 무엇입니까?

#include <iostream> 
using namespace std; 

class CRectangle { 
    int *width, *height; 
    public: 
    CRectangle (int,int); 
    ~CRectangle(); 
    int area() {return (*width * *height);} 
}; 

CRectangle::CRectangle (int a, int b) { 
    width = new int; 
    height = new int; 
    *width = a; 
    *height = b; 
} 

CRectangle::~CRectangle() { 
    delete width; 
    delete height; 
} 

int main() { 
    CRectangle rect (3,4), rectb (5,6); 
    cout << "rect area: " << rect.area() << endl; 
    cout << "rectb area: " << rectb.area() << endl; 
    return 0; 
} 

그런데 왜 나는 아래 대신 코드의 다른 부분을 사용하지 수에 는 // 예? 그것은 아래 코드를 사용하여 컴파일되지 않았지만 강제로 실행하면 올바른 결과가 생성됩니다. return (*width * *height); 코드

int area() { 
    return (*width * *height); 
} 

. 
. 
. 

CRectangle::~CRectangle() { 
    delete width; 
    delete height; 
} 

의 두 번째 부분에서

#include <iostream> 
using namespace std; 

class CRectangle { 
    //here I didn't initialize these two variables' pointers. 
    int width, height; 
public: 
    CRectangle (int a,int b); 
    ~CRectangle(); 
    int area() { 
    return (width * height); 
    } 
}; 

CRectangle::CRectangle (int a, int b) { 
    width = a; 
    height = b; 
} 

CRectangle::~CRectangle() { 

} 

int main() { 
    CRectangle rect (3,4), rectb (5,6); 
    cout << "rect area: " << rect.area() << endl; 
    cout << "rectb area: " << rectb.area() << endl; 
    return 0; 
} 
+3

컴파일되지 않은 코드는 실행할 수 없습니다. 마지막으로 성공한 빌드를 실행하지 않았습니까? – chris

+4

'width'와'height'는 포인터가 아니므로 직접 참조 부호를 사용하지 마십시오. 그리고 할당하지 않았기 때문에 삭제할 수 없습니다. – Barmar

+0

@Barmar가 말한 것 중 가장 정확한 방법은 처음이 아니라 그것을 말하는 것입니다. – chris

답변

3

, 당신은 포인터하지 widthheight을 역 참조하고 있습니다. 또한 소멸자에서 delete ing widthheightnew으로 초기화 된 포인터가 아니므로 잘못된 연산입니다. 무엇이 올바른 것은 @ 크리스가 자신의 의견에서 지적한 것을, 당신은 또한 소멸자를 제거 (선언과 정의를 모두 제거해야합니다) 수, 또한

int area() { 
    return (width * height); // Do not dereference width and height 
} 

. 
. 
. 

CRectangle::~CRectangle() { 
    // Do something else without the deletes or remove the destructor altogether 
} 

입니다.

+0

사실, 소멸자는 완벽하게 생략해도 괜찮을 것 같습니다. – chris

+0

@chris 예. 그러나 그것이 OP의 부분에서 약간의 혼란을 일으킬 것이라고 생각합니다. :) –

+0

지금은 그것을 정리하는 것이 좋습니다 :) 나는 거의 소멸자가 필요합니다. – chris

1

여기에는 메모리의 다른 위치에 있어야하는 정수에 대한 두 개의 포인터가 들어있는 구조가 있습니다. 따라서 CRectangle을 만들면 CRectangle 그 자체와 다른 곳에 두 개의 정수가있는 새 개체가 세 개 있습니다.

은 객체 지향 프로그래밍의 관점에서 CRectange는 응집 통해 두 int 객체와 연관된다.

#include <iostream> 
using namespace std; 

class CRectangle { 
    int *width, *height; 
    public: 
    CRectangle (int,int); 
    ~CRectangle(); 
    int area() {return (*width * *height);} 
}; 

지금 여기, 상황은 다른 두 int 객체는 CRectangle 내부에 포함됩니다. CRectangle 개체를 만들 때 해당 개체가 이미 내부에 존재합니다. 그들은 메모리에 주소를 가지고 있으므로 포인터를 만들 수 있지만 주소는 CRectangle의 주소를 기준으로 액세스됩니다. CRectangle의 멤버 함수 내에서 width에 액세스하면 실제로는 this->width을 의미합니다. 객체에 대한 포인터가 관련되어 있지만 보이지 않습니다. 우리가 객체에 대한 포인터를 가지고 있다면, 필드는 포인터에 대한 변위에 의해서만 발견 될 수 있습니다. C++은 어셈블리 언어가 아니므로 컴파일러는이 변위 계산을 수행하고 기계 코드를 생성합니다.

CRectangle과 두 개의 정수 사이의 연관은 이제 구성입니다. widthheight 포인터하지이기 때문에 area 기능에

class CRectangle { 
    //here I didn't initialize these two variables' pointers. 
    int width, height; 
public: 
    CRectangle (int a,int b); 
    ~CRectangle(); 
    int area() { 
    return (*width * *height); 
    } 
}; 

, 당신은, 포인터 역 참조에 대한 단항 연산자 *를 사용해서는 안된다. 그것은 적용되지 않습니다. (예 : 불편한 비 컴파일을 구체적으로 설명하는 예제를 제외하고는 게시하기 전에 예제를 게시하기 전에 코드가 제대로 컴파일되었는지 확인하십시오.)

관련 문제