만약 기초 클래스에 동적 할당이 있고 복사 생성자, 대입 연산자가 있으면 파생 클래스에 어떤 영향을 미칠까? (프로그래머의 머리가 깨지는 영향?)
// 기초 클래스.
class baseDMA
{
private:
char* label;
int rating;
public:
baseDMA(const char* l = "null", int r = 0);
baseDMA(const baseDMA& rs);
virtual ~baseDMA();
baseDMA& operator=(const baseDMA& rs);
};
위의 기초 클래스에는 동적 할당 변수, 복사 생성자, 대입 연산자가 있다.
class lacksDMA : public baseDMA
{
private:
char color[40];
public:
...
};
그 기초 클래스를 상속받는 파생 클래스가 있다. 이 파생 클래스에는 뭐 동적 할당 받을 것도 없고 다른 특별한 게 없다고 생각해보자. 이런 경우에는 명시적 파괴자, 복사 생성자, 대입 연산자를 만들어야 할까? 대답은 NO. 그럼 왜? 일단 파생 클래스에서는 뭐 동적 할당 같은 거 하는 게 없다. 그러니 디폴트 파괴자면 충분하다. 또한 파생 클래스에 특별한(?) 변수가 없기 때문에 파생 클래스는 디폴트 복사 생성자로 충분하다. 그럼 기초 클래스는? 기초 클래스를 복사 할 때는 알아서 기초 클래스의 복사 생성자가 실행된다. 대입 연산자도 이와 마찬가지로 생각하면 된다.
class lacksDMA : public baseDMA
{
private:
char * style;
public:
...
};
이런 경우에는 당연히 명시적 파괴자, 복사 생성자, 대입 연산자를 정의해주어야 한다. 파괴자는 각각의 클래스에 동적 메모리를 할당하는 변수를 해제해주면 된다.
lacksDMA::~lacksDMA()
{
delete[] style;
}
baseDMA::~baseDMA()
{
delete[] label;
}
주의할 것은 파생 클래스의 복사 생성자에 기초 클래스 복사 생성자를 써주어야 한다. 기초 클래스의 private 멤버에 파생 클래스가 접근할 수 없기 때문이다.
lacksDMA::lacksDMA(const lacksDMA& lacks)
: baseDMA(lacks)
{
...
}
여기서 기초 클래스의 매개변수로 파생 클래스를 사용했는데, 문제 없다. 왜? 기초 클래스는 파생 클래스 참조를 참조 할 수 있기 때문이다. 대입 연산자도 마찬가지로 기초 클래스를 호출해주어야 한다. 왜? 파생 클래스뿐만 아니라 기초 클래스도 같이 대입해야 하기 때문이다.
lacksDMA& lacksDMA::operator=(const lacksDMA& ls)
{
if (this == &ls)
return *this;
baseDMA::operator=(ls); // 기초 클래스 대입 연산자.
delete[] style;
style = new char[std::strlen(ls.style) + 1];
strcpy_s(style, std::strlen(ls.style) + 1, ls.style);
return *this;
}
생성자가 아닌 함수라 코드 블럭에서 호출해주었다.