프로그래밍/C++

[C++] 상속에서의 생성자 소멸자

갓똥 2019. 11. 26. 00:32
728x90
반응형

1. 상속에서의 생성자 소멸자

#include <iostream>
using namespace std;

class Base {
    int data;
public:
    Base()      { cout << "Base()"    << endl; }
    Base(int a) { cout << "Base(int)" << endl; }
    ~Base()     { cout << "~Base()"   << endl; }
};

class Derived : public Base {
public:
    Derived()      { cout << "Derived()"    << endl; }
    Derived(int a) { cout << "Derived(int)" << endl; }
    ~Derived()     { cout << "~Derived()"   << endl; }
};

int main() {
    Derived d;
}

 

실행결과

Base()
Derived()
~Derived()
~Base()

  ① 파생 클래스의 객체 생성시 생성자/소멸자 호출순서

    => 기반 클래스 생성자 / 파생 클래스 생성자

    => 파생 클래스 소멸자 / 기반 클래스 소멸자

 

int main() {
    Derived d(5);
}

 

실행결과

Base()
Derived(int)
~Derived()
~Base()

  ② 파생 클래스의 객체 생성시 인자가 있을 때

    => 기반 클래스 생성자는 디폴트 생성자 호출

    => 기반 클래스의 다른 생성자를 호출하려면 명시적으로 호출해야 한다.

 

    Derived(int a) : Base(a) { cout << "Derived(int)" < endl; }

 


2. 생성자/소멸자 호출의 정확한 원리

#include <iostream>
using namespace std;

class Base {
    int data;
public:
    Base()      { cout << "Base()"    << endl; }
    Base(int a) { cout << "Base(int)" << endl; }
    ~Base()     { cout << "~Base()"   << endl; }
};

class Derived : public Base {
public:
    Derived()      { cout << "Derived()"    << endl; }
    Derived(int a) : Base(a) { cout << "Derived(int)" << endl; }
    ~Derived()     { cout << "~Derived()"   << endl; }
};

int main() {
    Derived d(5);
}

  ① 정확한 원리

    => 파생 클래스의 생성자에서 기반 클래스의 생성자를 호출하는 코드를 컴파일러가 생성해 주는 것

 

#include <iostream>
using namespace std;

class Base {
    int data;
public:
    Base()      { cout << "Base()"    << endl; }
    Base(int a) { cout << "Base(int)" << endl; }
    ~Base()     { cout << "~Base()"   << endl; }
};

class Derived : public Base {
public:
    Derived()      : Base() { cout << "Derived()"    << endl; }
    Derived(int a) : Base() { cout << "Derived(int)" << endl; }
    ~Derived()     { cout << "~Derived()"   << endl; ~Base(); }
};

int main() {
    Derived d;
}

 


3. 상속에서의 생성자/소멸자 예제

// 1
class Animal {
public:
    Animal() {}
};

// 2
class Animal {
private:
    Animal() {}
};

// 3
class Animal {
protected:
    Animal() {}
};

class Dog : public Animal {
public:
    Dog() : Animal() {}
};

int main() {
    Animal a;
    Dog    d;
}

 

위의 코드에서 1 , 2 , 3번 코드 중 error가 나는 코드는 무엇일까?
    => 2, 3

  ① protected 생성자

    => 자기 자신은 객체를 만들 수 없지만 (추상적인 존재)

    => 파생 클래스의 객체는 만들 수 있게 하는 의미

 


4. 주의사항

#include <string>

class Person {
    std::string name;
    int age;
public:
    Person( std::string n, int a ) : name(n), age(a) {}
};

class Student : public Person {
    int id;
public:
    Student()      : id(0) {}
    Student(int i) : id(i) {}
};

int main() {
    Student s1;
    Student s2(100);
}

 

위의 코드는 얼핏봐선 문제 없어서 보이지만 컴파일 시 에러가 난다.
위의 2번에서 설명했던 것처럼 상속을 받으면 컴파일러가 Student : Person() 과 같이 디폴트 생성자를 붙여주는데
디폴트 생성자가 없기 때문에 발생한 에러이다.
#include <string>

class Person {
    std::string name;
    int age;
public:
    Person( std::string n, int a ) : name(n), age(a) {}
};

class Student : public Person {
    int id;
public:
    Student()      : Person("unknown", 0), id(0) {}
    Student(std::string n, int a, int i)
                   : Person(n, a), id(i) {}
};

int main() {
    Student s1;
    Student s2("kim", 20, 100);
}

  ① 기반 클래스에 디폴트 생성자가 없다면

    => 파생 클래스를 만들 때 반드시 기반 클래스의 생성자를 명시적으로 호출해야 한다.

    => 기반 클래스의 생성자를 명시적으로 호출하는 코드는 구현부(소스파일)에 작성한다.

728x90
반응형