자식 클래스에서 부모의 멤버변수를 초기화하여 사용하고 싶을 경우는 멤버 초기화리스트(멤버이니셜라이져)의 사용이 필수다.
초기화하는 방법에 앞서, 상속에 관한 이해가 필요하다.
클래스는 그 클래스의 속성을 표현하는 데이터들의 집합이다. 함수는 그 데이타에 대한 작업을 하는 도구다. 클래스의 객체를 생성하여 객체가 차지하는 메모리 공간의 크기를 재보면 멤버변수의 사이즈의 합과 같다. 함수가 얼마나 많든지 간에 객체의 크기는 멤버변수만의 총 사이즈다.
2015/04/28 - [프로그래밍/c++] - [C++]멤버이니셜라이져(멤버초기화리스트)
다음은 부모클래스와 상속관계에 있는 클래스의 객체를 생성하여 그 크기를 출력하는 코드다.
너무 당연한 결과다.
circle의 멤버변수는 int형 num 하나로 4byte,
point의 멤버변수는 int형 변수 x,y로 총 8byte.
합이 12바이트가 나온다.
나의 의문은 과연 "부모클래스의 멤버변수가 실제 메모리상으로 자식클래스의 객체에 더해졌냐?" 다.
이 의문에 대한 검증은 간단하다.
만약 그렇다면
자식클래스의 생성자로 부모클래스의 멤버 초기화가 가능해야 될 것이다..
다음은 검증을 위한 코드다.
부모의 멤버변수가private로 선언했기 때문에 자식 클래스에서 접근이 불가능 하다.
이 결과는 다음을 말해준다.
자식객체가 부모클래스 멤버를 멤버변수명을 통해 접근은 가능하지만, 부모 클래스의 객체가 따로 생성이 되었기 때문에, 제어 접근자(access control modifier)의 영향을 받는다는 뜻이다.
객체가 생성이 되었다면, 분명 생성자가 호출되었을 것이고, 그러면, 어떤 생성자가 호출 되었을까?
애초에 처음 코드의 경우는 디폴트 생성자가 호출 되었을 것이다.
만약 디폴트 생성자가 없을 경우라면?
참고
상속관계에서 생성자의 호출 순서는 부모->자식 순서, 소멸자의 호출 순서는 자식->부모 순서
위에서 갖은 의문을 하나씩 풀어보면.
해결방법
1. 부모의 제어 접근자를 protected 또는 public으로 바꾸면, 멤버변수명을 통해 접근이 가능하기 때문에 에러가 해결 될 것이다.(코드생략)
2. 1번의 경우에서 초기화 방법을 멤버 이니셜라이저로 다음과 같이 바꾸면 에러가 생긴다.
3. 제어 접근자를 private로 그대로 둔다면 방법은, 부모클래스의 생성자를 통해 멤버를 초기화 해야 하는데, 기존의 방법으로는 디폴트생성자만 호출되게 된다.
해결방법은 멤버 이니셜라이져(멤버 초기화 리스트)에서 부모클래스의 생성자로 초기화를 한다.
컴파일러 설계 방법에 따라 이유야 다르겠지만, 2번의 경우를 부연 설명하자면 이니셜라이저를 통한 부모 클래스의 멤버변수 초기화 방법을 3번(생성자를 통한 방법)으로 한정하기 위해서 라고 정리해 두려 한다.
같은 맥락으로 1번의 경우는 가능하지만 권하지 않는다. 클래스의 생성자는 존재의 이유(생성하는 방법)가 있고 1번처럼 임의의 초기화 방법은 안정성이 없기 때문이다.
다시 정리해보면.
상속관계에 있는 자식클래스의 객체 생성의 경우 부모클래스의 객체데이타가 자식에게 포함되는 것이 아니라 부모 클래스 객체가 따로 생성이 된다.(자식객체는 부모객체의 멤버에 대한 접근 권한을 제어 접근자에 따라서 부여 받는다. 단, 생성자를 통한 멤버변수의 접근은 private라도 허용하는데 생성자의 호출 방법에는 멤버 이니셜라이져(멤버초기화리스트)가 사용된다.