[42seoul] 4 circle - CPP Module 03

하이초·2022년 12월 26일
0

42seoul

목록 보기
4/11
post-thumbnail

CPP03 github 😋

1. ex00

👀 CPP03 ex00은 앞으로 ex03까지 상속의 바탕이 되는 클래스다. 아무래도 그냥 기본 스케치? 같은 거라 ex00은 크게 어려움이 없었다. 걍 만들라는 거 만들면 끝남.

아 그런데 세계관을 한 번 보고 과제를 하면 좀 더 재밌게...(아마도..) 할 수 있다. 대체 Trap 얘네들이 뭐 하는 애들이길래..? 하는 궁금증들을 조금이나마 해소할 수 있다.

2. ex01

👀 ex01부터 드디어 본격적인 상속이 시작된다!

🥨 가상 함수 virtual

  • 가상 함수 개념은 C++에서 처음 접해보는 개념이었다. 자바에서는 상속을 받게 될 경우 업캐스팅을 임의로 하지 않는 이상 자식이 오버라이딩한 멤버 함수를 호출할 경우 무조건 자식의 함수가 실행되지만, C++는 아니었다. 당황스러웠다.
  • C++는 자식에서 함수를 오버라이딩했다 하더라도 별도의 예약어를 사용하지 않으면 부모의 멤버함수가 실행된다. 기껏 오버라이딩 해놨더니 외않돼.. 하고 무척이나 당황스러웠다. 그리고 이걸 가능하게 하는 것이 바로!
  • virtual이다. 이 키워드를 잘 이해하려면 C++ 상속 메모리 구조에 대해 알아야 한다. 간단히 설명하자면 C++의 경우 일단 부모 클래스만큼의 공간이 할당되고, 자식에만 존재하는 멤버 변수나 함수 공간이 할당된다. 만약 부모에 void attack()이라는 함수가 존재하고, 자식이 이를 오버라이딩 했다고하자. 이때 virtual 키워드를 사용하지 않으면 컴파일러는 아무리 child.attack()처럼 호출해도 부모의 attack에 대한 메모리만 바라보게 된다. 컴파일러는 바보야.. 부모밖에 모르는 바보.. 그것이 정적바인딩..?
  • 여기서 virtual 키워드 힘차게 등장!!! 🤜 부모의 함수에 virtual void attack()처럼 키워드를 달아주면 컴파일러에게 "야 그거 자식이 오버라이딩 했을 수도 있을걸? 함 찾아봐~!" 라고 알려주게 되는 것이다. 그래서 virtual은 부모에 달아줘야 함. 이것이 동적바인딩..!
    - 이와 관련하여 virtual 키워드를 달아놓은 함수를 자식에서 오버라이딩하지 않으면 오류가 나지 않을까 했는데 잘 실행이 되었다. 😯 그냥 부모걸로 실행하면 되기 때문인가보다.
  • virtual은 소멸자에도 달아줘야 한다. 그래야 메모리 누수를 막을 수 있다! 실제 자식 클래스의 소멸자를 호출해서 제대로 날려줘야 함!
  • 이러한 가상함수의 경우 가상 함수가 하나라도 존재하는 클래스에 대해 '가상 함수 테이블'을 생성하여 저장한다.
    - 여기서 런타임시 어떤 함수를 실행하지 결정하는 동적 바인딩이 이루어지면서 오버헤드가 크게 발생한다고 한다. 가상함수는 이 포스팅에 정리가 잘 되어있다. 특히 중간에 있는 '가상 함수의 구현 원리' 이 부분에 나와있는 사진을 보면 가상 함수와 가상 함수 테이블, 실행원리 등이 잘 이해된다!

🥨 변수는 그럼 어떻게 하지?

  • 사실 이 과제에서 내가 제일 헤맸던 부분은 가상함수가 아니었다. 😶 내가 가장 헤맸던 부분은 '아니 다른 이름을 줬는데 왜 갑자기 소멸자에선 자식 이름만 나오ㄴ 거임..?' 이었다.
  • 나는 ScavTrap을 생성할 때 ClapTrap의 기본 생성자를 이용하지 않고 std::string _name을 변수로 받는 생성자를 사용하였다. 그래서 처음 생성 시에는 내가 준 그대로 ScavTrap XX's Parent ClapTrap 라고 분명히 이름을 뱉었는데 소멸자에서는 걍 ScavTrap XX 라고 뜨는 것이 아닌가... 환장
  • 알고보니 부모와 자식의 메모리가 따로 잡히는 게 아니라 부모의 공간만큼 무조건 할당 받고 거기에 추가적으로 자식에 필요한 메모리가 잡히는거라서 내가 변수를 따로 두지 않는 이상 name이라는 변수의 메모리주소가 같아서.. 그냥 덮어씌워지는 것이었다... 참나... ㅠ 자바 가져와 ㅠㅠ! 그래서 결국은.. 걍 별도의 변수를 설정하면 된다.. 이건 ex03에서 체험해 볼 수 있음! 변수는 가상함수가 아닌, scope의 힘을 빌려야 한다.

🥨 상속 접근제한자

  • 상속에도 public, protected, private과 같은 키워드를 통해 범위 한정을 해줄 수 있는데 사실상 public 외에는 별로 쓸 일이 없는 것 같다.
  • 각 접근제한자에 따라 그 개념보다 한 단계 낮은 범위로 부모의 변수와 함수를 상속받게 되기 때문이다. 만약 protected로 상속받게 될 시 부모에서 protected 보다 넓은 범위(=public~protected)로 선언된 것들이 protected로 내려오게 되고, private은 private 그대로 상속되어 자식에서 부모의 private에 있는 변수나 함수는 접근할 수 없게 된다. private은 더하다 걍 다 private으로 상속된다고 보면된다. 그러면 대체 상속을 사용하는 이유가 뭐란 말인가.
  • 그래서 걍 안전하게 public으로 가면 되는 것 같다. 굳이굳이 쓴다면 protected정도까지..? 부모 클래스가 전부 public, protected로 이루어져있다면 그 상속관계에 있는 애들만 사용한다고 보면 되니까는.. 뭐 그런거 아닐까?

3. ex02

👀 ex02는 ex01과 거의 비슷! 단지 ex01과 ex02는 서로 다른 클래스 고유의 스페샬 함수들을 가지고 있을 뿐이다.

🥨 다중 상속을 위한 빌드업

  • ex02까지는 마지막 ex03의 다중 상속을 위한 추진력을 얻기 위한 빌드업이어따..! 같은 느낌의 과제들이었다. 딱히 설명할게 없음.

4. ex03

👀 ex03은 다중 상속에 관한 과제였다. 자바에서는 다중 상속이 불가능해서 처음 접해보는 개념이어따..

🥨 다중 상속

  • ex03에서는 ex00~ex02에 만들어둔 클래스들을 가지고 다중 상속을 구현해야 했다.
  • 그렇다면 다중 상속이란 무엇인가? 말 그대로 한 클래스가 여러 클래스를 상속 받을 수 있는 것이다.
  • 여기서 발생하는 문제는 클래스 B, C가 클래스 A를 상속하고 있고, 클래스 D가 클래스 B, C를 상속할 때 클래스 A가 2번 생성된다는 점이다.

🥨 가상 상속

  • 여기서 또 거짓말처럼 가상 상속이 등장한다.
  • 위에서 살펴본 virtual 키워드를 상속에도 그대로 사용하면 된다.
  • 요런 느낌으로다가.. 위의 예제를 계속 사용하자면 클래스 B, C가 클래스 A를 virtual로 상속하면 된다. 그러면 클래스 D는 클래스 B, C에서 각각 클래스 A를 상속받는 것이 아니라 클래스 A를 직접 상속받게 된다. 따라서 한 번만 상속받게 됨!

🥨 Wshadow

  • 과제 마지막에 나와있는 Wshadow 옵션과 관련하여 잘 나와있는 글인것 같아 넣어본다 WShadow
  • 딱히 이번과제에서는.. 내가 scope를 사용해서 하거나 한 것은 없어서.. 해당 플래그를 넣어도 워닝은 발생하지 않았다. Wno-shadow는 -Wshadow 경고를 무시하게끔 해주는 플래그라고 한다... 알아만 두자..

🌱

플젝때문에 진짜 거의 한 두 달만에 다시 보게 된 CPP..
반갑다... 근데 앞으로 5개를 또 더 해야한다그러니까..
또 플젝하고 싶고 그러네..
플젝 회고는 또 언제쓰냐...

어쨌든...

🚴 CPP 가보자고!

profile
개발국대가 되는 그 날까지. 지금은 개발 응애.

0개의 댓글