이전 포스트에서 이어진다.
<>
유도 클래스는 기본 클래스의 멤버를 포함하므로, 유도 클래스가 초기화 되기 이전에 기본 클래스에서 상속된 부분이 반드시 초기화 되어야 함
유도 클래스 객체가 생성될 때
class Base
{
public:
Base() {
std::cout << "Base 생성자 생성 " << std::endl;
}
};
class Derived : public Base
{
public:
Derived() {
std::cout << "Derived 생성자 생성" << std::endl;
}
};
int main()
{
Derived d;
}
위의 코드를 실행 해보면 Base class의 생성자가 호출이 된다.
소멸자는 생성자와 반대 순서로 호출됨
즉, 유도 클래스가 소멸될 때,
유도 클래스는 기본 클래스의 생성자, 소멸자 및 오버로딩된 대입 연산자를 상속하지 않음
대신 , 기본 클래스의 생성자, 소멸자 및 오버로딩된 대입 연산자를 유도 클래스로부터 호출이 가능함
class Base
{
private:
int value;
public:
Base()
:value{0}
{
std::cout << "Base 인자 없는 생성자 생성 " << std::endl;
}
Base(int val)
: value{val}{
std::cout << "Base 인자 1개 생성자 생성" << std::endl;
}
};
class Derived : public Base
{
private:
int doubledValue;
public:
Derived()
:doubledValue{ 0 }
{
std::cout << "Derived 인자 없는 생성자 생성" << std::endl;
}
Derived(int val)
:doubledValue{ 2* val }
{
std::cout << "Derived 인자 1개 생성자 생성" << std::endl;
}
};
int main()
{
Base b;
Base b2{ 100 };
Derived d;//base 인자 없는 생성자 먼저 호출
Derived d2{ 100 };//base 인자가 없는 생성자가 호출 됨
}
위의 그림의 코드를 보면 Derived d2{100}; 을 선언했을 경우 base(int val) 생성자가 호출이 될 것 같지만 실제로는 base() 생성자가 호출이 된다. 이를 우리가 직접 정해줄 수 있다.
//Derived(int val)
// :doubledValue{ 2* val }
//{
// std::cout << "Derived 인자 1개 생성자 생성" << std::endl;
//}
Derived(int val)
:Base{ val },doubledValue {2 * val}//기본 생성자를 지정 가능함
{
std::cout << "Derived 인자 1개 생성자 생성" << std::endl;
}
위에서 작성했던 코드를 수정해 봤다. Base{ val } 생성자를 호출하게 하기 위해서 직접 지정해 주었다.
기본 클래스로부터 상속되지 않음
상속 전과 마찬가지로 컴파일러가 자동생성하지만, 필요한 경우 직접 구현해야함
기본 클래스에서 구현한 복사 생성자 호출 가능
기본 클래스의 복사 생성자를 직접 호출 가능
slice 과정을 거침
이동 생성자도 동일하게 동작
#include <iostream>
class Base
{
private:
int value;
public:
Base()
:value{0}
{
std::cout << "Base 인자 없는 생성자 생성 " << std::endl;
}
Base(int val)
: value{val}{
std::cout << "Base 인자 1개 생성자 생성" << std::endl;
}
Base(const Base& other)//복사 생성자
:value{other.value}
{
}
};
class Derived : public Base
{
private:
int doubledValue;
public:
Derived()
:doubledValue{ 0 }
{
std::cout << "Derived 인자 없는 생성자 생성" << std::endl;
}
Derived(int val)
:Base{ val },doubledValue {2 * val}//기본 생성자를 지정 가능함
{
std::cout << "Derived 인자 1개 생성자 생성" << std::endl;
}
Derived(const Derived& other)
:doubledValue{other.doubledValue}
{
}
};
int main()
{
Derived d1{ 100 };
Derived d2{ d1 };//base 인자가 없는 생성자가 호출 됨
}
나는 d1의 value의 값인 100으로 복사하고 싶은데 d2의 value의 값이 0으로 자동 초기화가 되는 것이 문제다
문제를 해결하기 위해서는
Derived(const Derived& other)
:Base{other},doubledValue{other.doubledValue}
{
}
Derived(const Derived& other)
:Base{other},doubledValue{other.doubledValue}
{
}위의 코드를 중단점을 찍어서 실행시켜 보자!
즉, slice란 유도 클래스로터 기본 클래스의 필요한 부분만 가져와서 사용 할 수 있다는 것이다. 이것이 Base 클래스에서 Derived를 사용 가능한 이유다.