Search
Duplicate
♟️

CPP04 를 파헤쳐보자..

간단소개
CPP04 (보너스 제외)
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C++
Scrap
태그
9 more properties
Keyword: Subtype polymorphism, abstract classes, interfaces

EX00: Polymorphism

[Mandatory]

For every exercise, you have to provide the most complete tset you can.
Constructor and destructor of each class must display specific message.
Don’t use the same message for all classes.
Start by implementing a simple base class called Animal. It has one protected attribute:
std::string type;
Implement a Dog class that inherits frm Animal.
Implement a Cat class that inherits from Animal.
These two derived classes must set their type field depending on their name.
The Dog’s type will be initialized to “Dog”, and Cat’type to “Cat”
The type of the Animal class can be left empty or set to the value of your choice.
Every animal must be able to use the member function: makeSound()
Running this code should print the specifit sounds of the Dog and Cat classes, not the Animal’s
To ensure you understood how it wotks, implement a WrongCat class the inherits from a WrongAnimal class
If you replace the Animal and the Cat by the wrong ones in the code above, the WrongCat should output the WrongAnimal sound.

[과제 요구 사항 해석]

1.
provide the most complete test you can.
: 각 과제에서 요구하는 내용을 보여줄 수 있는 메인 함수를 작성하라는 의미이다.
2.
Constructor and destructor of each class must display specific messages.
: 각 클래스의 생성자와 소멸자는 반드시 자신만의 메세지를 보여줘야 한다는 의미이다.
3.
베이스 클래스인 Animal을 만들고 protected 로 std::string type 을 클래스 변수로 가져라.
: 베이스 클래스인 Animal 이 protected 로 클래스 변수를 가지라는 의미이다. 이는 자식 클래스에서도 접근이 가능하다.
4.
Dog, Cat 클래스는 Animal 클래스를 상속한다.
5.
이 두 파생 클래스는 그들의 타입을 그들의 클래스 이름에서 따온다.
: 각 파생 클래스가 그들의 타입을 Dog, Cat으로 초기화하도록 생성자를 만들면 된다.
6.
Every animal must me able to use the member function: makeSound(). It will print an appropriate sound.
: 모든 클래스 (Animal, Dog, Cat) 클래스는 makesound() 함수를 가진다. 이는 Animal 클래스에서 만들어지고 파생 클래스에서 오버라이딩(재정의) 하는 방식으로 만족될 수 있다.
7.
Runnint this code should print the specific sounds of the Dog and Cat classes, not the Animal’s
int main() { const Animal* meta = new Animal(); const Animal* j = new Dog(); const Animal* i = new Cat(); std::cout << j->getType() << " " << std::endl; std::cout << i->getType() << " " << std::endl; i->makeSound(); //will output the cat sound! j->makeSound(); meta->makeSound(); ... return 0; }
C++
복사
: Animal 클래스 포인터로 선언된 Cat, Dog 은 자신만의 makesound()를 출력해야 한다. 이는 Animal 클래스의 맴버 함수인 makeSound()함수가 가상 함수로 선언되면 된다. 이로 인해 동적 바인딩으로 각 객체에 맞는 makeSound()가 호출될 수 있다.
8.
잘 이해했는지 확인하기 위해 WrongCat, WrongAnimal 을 선언하고 Cat, Animal을 대체해봐라.
: virtual 키워드로 makesound()를 선언하지 않았다면, Cat, Dog 의 객체가 makeSound()를 호출하더라도, Animal 포인터에 의해 호출되기 때문에 Animal 클래스의 makeSound()가 호출된다. 이 가상함수를 잘 이해했는지 확인하는 메인 함수 및 클래스를 구성해보자.

[The code]

[과제를 통해 배운 것]

1.
Polymorphism
: 다형성의 의미는 다음과 같습니다. “다형성이란 어떤 객체가 상황에 따라 기능이나 속성이 여러가지 형태를 가질 수 있음을 의미한다” 그리고, 객체지향언어에서 다형성은 같은 결을 따릅니다. 객체지향언어에서의 다형성은 “어떤 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것”을 의미합니다.
C++ 에서의 다형성은 ‘오버로딩, 오버라이딩, 가상함수’ 를 통해 구현됩니다. 오버로딩과 오버라이딩을 통해 어떤 객체의 기능과 속성이 상황에 따라 여러가지 형태를 가질 수 있으며, 상위 클래스의 참조변수(어떤 값이 들어가있는 주소를 가지고 있는 변수)를 통해 하위 클래스의 여러 객체를 상황에 맞게 참조할 수 있습니다.
2.
Virtual keyword
: 다형성을 구현하는 한 부분인 virtual 키워드는 어떤 객체가 상황과 맥락에 맞는 기능이나 속성을 사용할 수 있도록 하는 것입니다. 위의 다형성의 설명에서 ‘한 타입의 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것을 의미합니다.” 그리고 한 타입의 참조 변수를 통해 여러 타입의 객체를 참조하려면 virtual 키워드를 통해 동적바인딩외 되어야 합니다.

EX01: I don’t want to set the world on fire

[Mandatory]

각 클래스의 생성자와 초기화는 반드시 특정한 메세지를 보여줘야 합니다.
: 각 클래스의 생성자와 초기화는 각기 다른 특정한 메세지를 표준 출력으로 출력해야 한다.
Brain 이라는 클래스를 만들어라.
: 100개의 std::string 배열을 가지고 있다. 변수 이름은 ideas 이다.
Dog and Cat class
: 두 클래스는 private으로 Brain* 변수를 가집니다.
: 두 클래스의 생성자가 Brain 인스턴스 변수를 생성한다. (new Brain)
: 두 클래스의 소멸자가 Brain 인스턴 변수를 해제한다. (delete Brain)
main function
: Animal 클래스의 배열을 만들고 채워라.
: 이 배열의 절반은 Dog 이고, 나머지 절반은 Cat 객체이다.
: 프로그램의 끝에서 이 배열의 메모리를 해제해라.
: 이 때, 반드시 Animal 로써 Dog 과 Cat 을 해제해라.
: 예상되는 순서에따라 소멸자가 호출되어야 한다.
메모리 누수를 확인하는 것일 잊지 말아라.
Dog, Cat의 복사본이 얕으면 안된다. 반드시 깊은 복사가 되었는지 확인해 봐라.

[과제 요구 사항 해석]

1.
Dog, Cat 클래스는 Brain* 를 private 키워드로 보유해야 합니다.
: 이는 두 클래스가 private 키워드로 Brain* 를 맴버 변수로 가지고 있어야 한다는 의미입니다.
2.
Dog, Cat 클래스는 생성자에서 new Brain() 키워드를 사용해야 합니다.
: 두 클래스의 생성자를 통해서 Brain 포인터를 new Brain() 으로 동적할당 및 초기화를 해야 한다는 의미입니다.
3.
Dog, Cat 클래스는 소멸자 호출 시, Brain 멤버 변수에 할당된 메모리를 해제해야 합니다.
: 소멸자 호출 시, delete 호출로 Brain 포인터가 가리키는 메모리를 해제해야 합니다.
4.
메인 함수에서 Animal 오브젝트의 배열을 생성하십시오. 절반은 Dog, 나머지 절반은 Cat 객체입니다. 그리고 함수 끝에 Animal 배열을 해제하십시오.
: 메인 함수에서 Animal 객체를 담는 배열을 생성한다. 절반은 Dog 나머지는 Cat을 가리키는 포인터 배열로 생성한다. 그리고 함수 끝에 이 배열을 해제하하도록 한다.
5.
배열을 해제할 때 Animal 객체인 채로 해제하십시오.
: 객체를 따로 캐스팅 하지 말자. Animal 로 생성했으니, Animal로 해제하자.
6.
Dog, Cat 클래스에서 일어나는 복사는 깊은 복사로 하자.
: Dog, Cat 의 Brain은 포인터이고, 동적 할당된 메모리를 가리키고 있다. 이 때문에 복사 생성이나 대입 연산을 할 때, 얕은 복사를 하면 문제가 발생한다. 깊은 복사로 복사하자.

[The code]

[과제를 통해 배운 것]

1.
delete object
: 객체를 해제하면, 객체의 소멸자가 호출된다.
2.
virtual desturctor 링크
: 파생 클래스 객체를 가리키는 포인터가 기반 클래스로 정의되어 있다면, 이 포인터를 delete 한다면, 기반 클래스의 소멸자가 호출된다. 이는 메모리 누수를 일으킬 수 있으니, 파생 클래스의 소멸자를 제대로 호출하도록 유도해야 한다. 이를 위해 기반 클래스의 소멸자에 virtual 키워드를 붙여야 한다. 이 키워드를 통해 런타임 동안 동적바인딩이 이루어지게 되고 객체에 맞는 올바른 함수가 호출되게 된다. (이 때는 올바른 소멸자가 호출된다.)
3.
Deep copy vs shallow copy 링크
: 깊은 복사와 얕은 복사의 핵심은 원본 객체와 복사본 객체가 같은 것을 가리키냐 입니다. 얕은 복사에서는 복사본 객체가 원본 객체와 같은 데이터를 가리키고 있습니다. 이는 포인터 혹은 참조의 복사때문입니다. 깊은 복사에서는 복사본 객체가 새로운 데이터를 생성하고 이를 가리키고 있습니다.

EX02: Abstract class

[Mandatory]

Creating Animal object doesn’t make sense after all.
default Animal class should not be instantiable.
Fix the Animal class so nobody can instaniate it. Everything should work as before.
If you want to, you can update the class name by adding a A prefix to animal.

[과제 요구 사항 해석]

1.
애니멀 객체를 만드는 것은 말이 안된다.
: 그렇다. 세상에 동물이라 불리는 생명체가 어디에 있다는 말인가?
2.
default Animal class should not be instaniable.
: 위의 연장선이다. 그렇기 때문에 애니멀 객체를 만들수 있어서는 안된다.
3.
누구든 애니멀 객체를 만들지 못하도록, 에니멀 클래스를 수정해라.
: ‘추상 클래스’ 는 객체를 만들지 못한다. Animal class를 추상 클래스로 만들라는 이야기이다.
4.
만약 원한다면, 에니멀 클래스에 접두사 ‘A’를 붙여도 된다.
: 추상 클래스이기 때문에 추상을 의미하는 A 를 클래스 이름에 붙여도 된다는 의미이다.

[The code]

[과제를 통해 배운 것]

1.
순수 가상 함수
: 순수 가상 함수는 ‘무엇을 하는지 정의되어 있지 않은 함수’를 의미합니다. 다시 말해 이 함수는 반드시 오버라이딩이 되어야 합니다. 순수 가상 함수는 다음과 같이 정의됩니다.
public: virtual void makeSound(void) const = 0; // 함수의 몸통 없이 '= 0;' 이 붙는다.
C++
복사
당연하게도 이 함수가 뭘 하는지 정의되어 있지 않기 때문에 이 함수를 호출하는 것이 불가능합니다. 그렇기 때문에 이 순수 가상 함수를 포함하는 객체를 인스턴스화 시킬 수 없습니다. C++ 개발자들은 순수 함수를 포함한 클래스가 객체를 만들지 못하도록 컴파일 단계에서 막습니다.
EX02 과제애서 요구하는 바는 ‘Animal class 는 객체를 만들지 못한다.’ 이고, 이는 Animal classs 가 순수 가상 함수를 포함하도록 수정되면 됩니다.
2.
추상 클래스
: 순수 가상 함수를 최소 한개 포함하고 있는 클래스를 추상 클래스라고 합니다. 따라서 이 과제의 요구사항인 ‘Animal Class는 인스턴스를 만들지 못한다’의 요구사항은 Animal class 가 가상 함수를 최소 하나 이상 포함하도록 수정하면 됩니다. 그리고 추상 함수로 만들어진 makeSound(void) 함수는 상속된 Dog, Cat 클래스에서 오버라이딩 되어 각 객체에 맞추어서 사용됩니다.
3.
concrete class
: 인스턴스를 생성할 수 있는 클래스를 concrete class (구상 클래스) 라고 한다. 미완성 클래스인 추상 클래스에 미정의된 기능을 구현한 클래스이다.

참고 자료