반응형

상속(Inheritance)

  • 정의
    • 클래스 생성시 다른 클래스의 특성을 그대로 이어 받는 방법
  • 상속 문법
    • Student, Professor의 공통 특징을 모아서 Person 클래스를 설계
    • Student, Professor 클래스를 생성시 Person 클래스를 상속 
  • 대부분의 객체지향 언어에서 제공
    • C+++ : class Student : public Person
    • JAVA : class Student extends Person
    • C# : class Stduent : Person
  • 장점
    • 중복 코드 제거
    • 상속을 통해서 기존 클래스에서 새로운 특징 추가
    • 다형성(Polymorphism)을 활용한 객체 지향 디자인
  • UML 표기법
    • 하위(파생)클래스에서 상위(기반) 클래스를 향하도록 화살표를 사용해서 표기
// 사람의 공통 특성을 각 클래스의 멤버로 소유한 예
class Student
{
    int age; // 사람의 공통 특성
    std::string name; // 사람의 공통 특성
    int id; // 학생 번호
};

class Professor
{
    int age; // 사람의 공통 특성
    std::string name; // 사람의 공통 특성
    int major; // 전공
};

int main()
{

}

///////////////////////////////////////////////////////

// 사람의 공통 특성을 Person 클래스로 분리하여 상송 받은 예
// Base(기반), Super
class Person
{
    int age;
    std::string name;
};

// Derived(파생), Sub
class Student : public Person
{
    int id; // 학생 번호
};

class Professor : public Person
{
    int major; // 전공
};

int main()
{
}

상속(Inheritance)의 접근자

  • private:
    • 멤버함수와 friend 함수만 접근 가능
  • protected:
    • 멤버 함수와 friend 함수 접근 가능
    • 파생 클래스의 멤버 함수, 파생 클래스의 friend함수에서 접근 가능
  • public:
    • 멤버 함수와 모든함수에서 접근 가능
class Base
{
private:
    int a;
protected:
    int b;

public:
    int c;
};

class Derived : public Base
{
public:
    void foo()
    {
        a = 10; // 파생 클래스에서 private 접근 error
        b = 10; // 파생 클래스에서 protected 접근 ok
        c = 10; // 파생 클래스에서 public 접근 ok
    }
};

int main()
{
    Base b;
    b.a = 10; // 일반 함수에서 private 접근 error
    b.b = 10; // 일반 함수에서 protected 접근 error
    b.c = 10; // 일반 함수에서 public 접근 ok
}

상속(inheritance) 생성자/소멸자

  • 파생 클래스 객체 생성시 기반 클래스의 생성자/소멸자도 호출됨
  • 생성자/소멸자 호출 순서
    • 기반 클래스 생성자
    • 파생 클래스 생성자
    • 파생 클래스 소멸자
    • 기반 클래스 소멸자
  • 기반 클래스의 생성자는 항상 디폴트 생성자가 호출됨
    • 기반 클래스에 디폴트 생성자가 없을 경우 기본적으로는 파생 클래스의 객체를 생성 할 수 없음
  • 기반 클래스의 디폴트 생성자가 아닌 다른 생성자를 호출하는 방법
    • 파생클래스의 초기화 리스트에서 기반 클래스의 생성자를 명시적으로 호출
// 파생 클래스 객체 생성시 기반클래스의 디폴트 생성자가 호출 예
#include <iostream>

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

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


int main()
{
    Derived d(5);
}
// 파생 클래스의 생성자에의 파라미터 전달 생성시 기반클래스의 Base(int a) 생성자가 호출 예
#include <iostream>

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

class Derived : public Base
{
public:
    Derived() {}
    Derived(int a) : Base(a) {} // 기반 클래스의 Base(int a) 생성자 호출 명시
    ~Derived() {}
};


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

상속(inheritance) 생성자/소멸자 호출 원리

  • 파생 클래스의 생성자에서 기반 클래스의 디폴트 생성자를 호출하는 코드를 컴파일러가 제공함
class Base
{
public:
    Base() { std::cout << "Base()" << std::endl;  }
    Base(int a) { std::cout << "Base(int)" << std::endl; }
    ~Base() { std::cout << "~Base()" << std::endl; }
};

class Derived : public Base
{
public:
    Derived() {} // 컴파일러에 의해 내부 코드가  Derived() : Base() {}
    Derived(int a) {} // 컴파일러에 의해 내부 코드가  Derived(int a) : Base() {}
    ~Derived() {} // 컴파일러에 의해 내부 코드가  ~Derived() { ...; 기반 클래스 소멸자 ~Base();}
};

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

Public 생성자

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

class Dog : public Animal
{
public:
};

int main()
{
    // 다음중 에러를 모두 골라 보세요.
    Animal a; // Error 없음, Animal() {} 생성자 사용
    Dog d; // Error 없음, 컴파일러가 기본 생성자 생성, Animal() {} 생성자 호출
}

Private 생성자

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

class Dog : public Animal
{
public:
};

int main()
{
    // 다음중 에러를 모두 골라 보세요.
    Animal a; // Error, Animal() {} 생성자 private이라 접근 불가
    Dog d; // Error, Dog 생성자는 컴파일러가 제공하고, 기반 클래스인 Animal() {} 생성자 호출시 에러
}

Protected 생성자

  • 자신의 객체는 만들수 없지만 파생 클래스의 객체는 만들 수 있음
  • Animal은 추상적(Abstract) 개념이므로 객체가 존재 불가
  • Dog는 구체적(Concrete) 존재이므로 객체가 존재할 수 있음
class Animal
{
protected:
    Animal() {}
};

class Dog : public Animal
{
public:
};

int main()
{
    // 다음중 에러를 모두 골라 보세요.
    Animal a; // Error, Protect 생성자를 일반 함수에서 호출 불가
    Dog d; // OK, 컴파일러가 Dog 디폴트 생성자 제공하고, Animal Protected 생성자 호출됨
}
반응형

'프로그래밍 언어 > C++' 카테고리의 다른 글

C++ 오버라이드, 가상함수(Override & Virtual Function)  (0) 2019.05.12
C++ 업캐스팅(Up Casting)  (0) 2019.05.12
C++ STL 정리  (0) 2019.05.12
C++ STL 정책(Policy Base)  (0) 2019.05.12
C++ STL 알고리즘(Algorithm)  (0) 2019.05.12

+ Recent posts