C++

[C++] 42SEOUL CPP03 개념 공부하기

madylin 2023. 7. 28. 15:09
반응형

(42Seoul의 CPP03 과제를 진행하며 공부한 내용을 작성한 TIL을 정리한 글 입니다.)


개념 공부📓

클래스 상속

  • 기존 클래스의 특성과 기능을 새로운 클래스가 물려받는 것
  • 상속을 통해 기존 클래스의 멤버 변수와 멤버 함수를 그대로 사용하거나, 새로운 멤버 변수와 멤버 함수를 추가하여 새롭게 정의할 수 있음
  • 상속을 통해 만들어진 새로운 클래스를 ‘파생 클래스’ 또는 ‘하위 클래스’ 라고 하며, 기존 클래스는 ‘기본 클래스’ 또는 ‘상위 클래스’ 라고 함
  • 클래스 상속 방법
class BaseClass {
	// 기본 클래스의 멤버 변수와 멤버 함수 선언
}

class DerivedClass : access-specifier BaseClass {
	// 파생 클래스의 멤버 변수와 멤버 함수 선언
}
  • BaseClass : 기본 클래스
  • DerivedClass : 파생 클래스로, ‘BaseClass’를 상속하는 것을 나타내기 위해 콜론(’:’) 뒤에 ‘access-specifier BaseClass’ 와 ‘BaseClass’ 를 명시함
  • ‘access-specifier BaseClass’ : 접근 제어 지시자로, 기본 클래스의 멤버들에 대한 파생 클래스의 접근 권한을 설정. 주로 ‘public’, ‘protected’, ‘private’ 키워드를 사용함
    • public : 기본 클래스의 public, protected, private 멤버들이 그대로 상속됨
    • protected : 기본 클래스의 protected 지시자보다 접근 범위가 넓은 멤버(public)는 protected 로 변경되어 상속됨
    • private : 기본 클래스의 private 지시자보다 접근 범위가 넓은 멤버(public, protected)는 private 으로 변경되어 상속됨

클래스 상속 함수 오버라이딩

class Base {
public:
    virtual void printMessage() const {
        std::cout << "This is Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    // Base 클래스의 printMessage() 함수를 오버라이딩
    void printMessage() const override {
        std::cout << "This is Derived class" << std::endl;
    }
};

int main() {
    Base baseObj;
    Derived derivedObj;

    // 기존 클래스의 함수 호출
    baseObj.printMessage();    // 출력: "This is Base class"

    // 파생 클래스에서 오버라이딩한 함수 호출
    derivedObj.printMessage(); // 출력: "This is Derived class"

    return 0;
}
  • 기존 클래스에서 상속받은 함수를 파생 클래스에서 수정하여 사용하고 싶을 경우, 함수 오버라이딩을 통해 해당 함수를 새로 정의하면 됨
  • 함수 오버라이딩을 위해 다음의 조건을 만족해야 함
    • 기존 클래스에서 오버라이딩 하려는 함수는 가상(virtual) 함수로 선언되어야 함
    • 기존 클래스의 함수와 함수의 이름, 반환 타입, 매개변수 리스트가 동일해야 함

클래스 상속 생성자 오버라이딩

class Base {
public:
    int value;

    Base() : value(0) {
        std::cout << "Base default constructor called." << std::endl;
    }

    Base(int val) : value(val) {
        std::cout << "Base parameterized constructor called." << std::endl;
    }
};

class Derived : public Base {
public:
    // 기본 클래스의 생성자를 오버라이딩
    Derived() : Base() {
        std::cout << "Derived default constructor called." << std::endl;
    }

    // 기본 클래스의 생성자를 오버라이딩하며 추가적인 파라미터 사용
    Derived(int val) : Base(val) {
        std::cout << "Derived parameterized constructor called." << std::endl;
    }
};

int main() {
    Base baseObj;          // 출력: "Base default constructor called."
    Derived derivedObj;    // 출력: "Base default constructor called.", "Derived default constructor called."

    Base baseObj2(42);     // 출력: "Base parameterized constructor called."
    Derived derivedObj2(99);  // 출력: "Base parameterized constructor called.", "Derived parameterized constructor called."

    return 0;
}
  • 생성자와 소멸자 오버라이딩은 위의 함수 오버라이딩과 다름
  • 상속된 변수들의 초기화는 기존 클래스의 생성자에서 진행하기 때문에, 파생 클래스의 생성자에서 기본 클래스의 생성자를 호출해야 함.
  • 오버라이딩 시, 파생 클래스의 생성자가 호출되면 먼저 기본 클래스의 생성자가 호출되고, 이후 파생 클래스의 생성자가 실행됨.

다이아몬드 상속

  • 하나의 클래스가 두개 이상의 클래스로부터 상속 받는 구조
    A
  /   \
B       C
  \   /
    D
  • 다이아몬드 상속에는 D 클래스에서 A 클래스의 멤버 변수나 멤버 함수에 접근할 때, B나 C 중 어떤 클래스를 기반으로 하는지 모호하다는 문제가 있어 잘 사용하지 않는 상속 방법
  • C++ 에는 다이아몬드 문제를 해결하기 위해 가상 상속을 지원함.
    • 가상상속은 다이아몬드 상속 구조에서 공통된 기본 클래스를 가상으로 상속하여, 다이아몬드 구조를 일반적인 트리구조로 바꿔주는 기법
    • virtual 키워드를 사용하여 공통된 클래스를 가상으로 상속
class A {
    // ...
};

class B : virtual public A {
    // ...
};

class C : virtual public A {
    // ...
};

class D : public B, public C {
    // ...
};
  • B 와 C에서 A의 멤버변수와 멤버함수를 공유하기 때문에, B > C 순서로 생성자가 호출되며 A의 멤버변수를 초기화할 경우, C의 내용으로 덮어쓰기 됨

 

 

 

 

 

제가 공부한 내용을 기록하고 있습니다.

혹시 수정이 필요한 부분이 있다면, 댓글로 지적 부탁드립니다!

선한 관심과 도움 감사드립니다😊

반응형

'C++' 카테고리의 다른 글

[C++] 42SEOUL CPP04 개념 공부하기  (0) 2023.07.28
[C++] 42SEOUL CPP02 개념 공부하기  (0) 2023.07.28
[C++] 42SEOUL CPP01 개념, 함수 공부하기  (0) 2023.07.28