컴퓨터라는 클래스가 있다고 가정을 해봅시다.
그리고 노트북이라는 클래스를 만들고 싶을 때 일반적인 컴퓨터의 속성을 가지고 있을 것입니다. 유사성이 비슷한 두 클래스이지만 screen size와 weight같은 특수한 노트북의 속성들이 추가적으로 필요할 것입니다.
하지만 상속을 이용하면 더 간단하게 이용할 수 있습니다.
상속
컴퓨터로부터 derived된 클래스라고 표현을 하며 컴퓨터는 base 클래스, 확장해서 만든 클래스를 derived 클래스라고 합니다. 이 관계는 is a relationship이라고 부릅니다. A notebook is a computer라고 부릅니다.
class Computer {
public:
string manufacturer;
string processor;
int ramSize;
int diskSize;
double processorSpeed;
double computerPower() {
return ramSize * processorSpeed;
}
double getRamSize() { return ramSize; }
double getProcessorspeed() { return processorSpeed; }
int getDiskSize() { return diskSize; }
};
class Notebook : public Computer {
public:
double screenSize;
double weight;
double getScreenSize() {
return screenSize;
}
double getWeight() {
return weight;
}
};
class Person {
private:
string name;
int age;
string address;
public:
void live();
};
class Student : public Person {
string school;
string std_id;
public:
void study_hard_or_die();
}
이렇게 계층 관계를 만들어가는 것입니다. 현대 프로그램들은 이런 식으로 계층간의 관계를 가지며 활용됩니다.
상속에 의해 클래스들은 계층을 형성하고 계층 구조의 맨 위에는 베이스 클래스가 있습니다. 다른 클래스들이 직접 또는 간접적으로 상속받습니다. 이러한 상속을 받은 클래스를 파생 클래스라고 합니다.
파생클래스 객체의 생
class Base {
int baseMem;
public:
Base() {
cout << "Consructing base\n";
}
};
class Derived : public Base {
int derivedMem;
public:
Derived() {
cout << "Constructing derived \n";
}
};
int main() {
Derived d;
return 0;
}
Constructing base
Constructing derived
이렇게 호출이 됩니다. 이 결과를 볼 때 우리가 유추할 수 있는 것은 derived 클래스는 base 클래스를 안에 포함하고 있는 관계로 볼 수 있습니다. base 클래스로부터 상속받은 것이 있고 생성자라는 것은 어떤 것을 생성하면서 초기화하는 일을 합니다.
Derived 클래스 안에는 base 멤버, derivedMem이 있습니다. 이 두개의 멤버를 생성하는 일인데 Derived() 생성자가 다 하는 것이 아닌 Base()를 먼저 생성해서 상속받은 것들을 작업하고 이후 Derived() 생성자가 다룬다는 것을 알 수 있습니다.
클래스가 하나라도 생성자를 만들거면 default 생성자도 만들어야 합니다. computer() = default;
상속과 생성자
파생클래스의 생성자는 항상 먼저 베이스클래스의 생성자를 호출합니다. 즉 베이스클래스로부터 상속받은 멤버들을 초기화하기 위해 베이스클래스의 생성자를 먼저 건드는 것입니다.
1. 생성자의 초기화 리스트에서 베이스클래스 생성자를 명시적으로 호출
2. 그렇지 않을 경우 자동으로 베이스클래스의 디폴트 생성자가 호출됩니다. 이 경우 베이스클래스에 디폴트 생성자를 해줘야 합니다.