가) Car 클래스를 만들고, Ptr객체에 포인터 형식으로 넣어서,
생성자에서 할당, 소멸자에서 해제하라.
나) Car를 외부에서 동적할당 하고, 해제 코드는 작성하지 마라.
밑의 코드가 가능하게 포인터 클래스와, Car 클래스를 만들어라.
Ptr p = new Car;
p->Go();
(*p).Go();
: 객체이지만, 포인터처럼 동작하는 객체
- 포인터처럼 동작하게 하기 위해서 ->, 를 만들어야 함.
( * )포인터 연산자의 경우, 반환값은 복사 방지를 위해 참조반환 해야 함.
: Car를 포인터가 아닌 객체로 선언했지만, 포인터와 동일하게 new 하면서 초기화 하고 있음.
#include <iostream>
class Car
{
public:
void Go() { std::cout << "Go" << std::endl; }
~Car() { std::cout << "~Car" << std::endl; }
};
class SPtr
{
Car* ptr;
public:
SPtr(Car* p = 0) : ptr(p) {}
~SPtr() { delete ptr; }
Car* operator->() { return ptr; }
Car& operator*() { return *ptr; }
};
int main()
{
// SPtr의 객체 p가 Car의 포인터 처럼 사용
// Car* p = new Car;
SPtr p = new Car; // SPtr p( new Car )
p->Go(); // p + a : p.operator+(a)
// (p.operator->())Go()
// (p.operator->())->Go()
(*p).Go(); // p.operator*()
}
'-> 연산자' 와, '. 연산자' 를 이용해 객체 내부에 있는
포인터 객체에 접근할 수 있게 해야 함.
포인터가 아닌 객체이므로, 반드시 스코프를 벗어나면 소멸자가 호출되므로.
클래스 내에 해제할 수 있음.
실제 포인터 객체를 쓸 경우, 객체가 아니라서,
클래스 외부에서 유저가 관리해야 함.
생성 / 복사 / 대입 / 파괴의 모든 과정에서 원하는 작업을 수행할 수 있음.