다형성
18일차에 이어서 다형성에 대해 좀 더 자세히 알아보자!
class Person {
protected:
string name;
string position;
public:
void test() {
cout << "Person 클래스의 테스트 함수입니다. \n";
}
//getter
string get_position() {
return position;
}
//void get_position2() {
// cout << position;
//}
};
class Student: public Person {
string stu_id;
public:
Student(string position) {
this->position = position;
}
void aaa() {}
void test() {
cout << "Student 클래스의 테스트 함수입니다. \n";
}
};
class Instructor : public Person {
public:
Instructor(string position) {
this->position = position;
}
};
int main() {
//Person p;
Person p = Person(); //생성자 호출
//p.test();
//앞에 있는 클래스의 생성자만 불러올 수 있다.
//Person p2 = Student(); //부모클래스로 자식클래스의 인스턴스를 호출(Person 의 멤버들만 가져올 수 있음)
//p2.test();
//p2.aaa(); student의 있는 메소드를 불러오지 못함
Person p3[4] = { Instructor("나미리 쌤"), Student("짱구"),Student("철수") ,Student("맹구") };
for (int i = 0; i < 4; i++) {
cout << p3[i].get_position() << endl;
}
}
실습
(1) Candy 클래스와 Chocolate 클래스를 만들어주세요.
조건 1. Candy 클래스는 맛, 가격, 상품이름, 제조회사를 의미하는 변수를 가지고 있어야 합니다.
조건 2. Chocolate 클래스는 모양, 가격, 상품이름, 제조회사를 의미하는 변수를 가지고 있어야 합니다.
조건 3. Candy클래스와 Chocolate 클래스는 모두 같은 상위 클래스(Snack)로부터 상속을 받아야 합니다.
(2) 메인 함수에 snackBasket이라는 이름의 배열을 만들어주세요.
조건 1. 위에서 만든 Candy 클래스와 Chocolate 클래스로 각각 두 개의 객체 만들기만든 총 4개의 객체를 snackBasket이라는 배열에 넣어주세요.
조건 2. 4개의 인스턴스를 모두 넣었다면 메인 함수에서 반복문을 통해 snackBasket 안에 들어 있는 간식들의 상품 이름을 출력해주세요.
class Snack {
protected:
string money;
string name;
string factory_name;
public:
//getter
string get_name() {
return name;
}
};
class Candy:public Snack {
string taste;
public:
Candy(string money, string name, string factory_name, string taste) {
this->money = money;
this->name = name;
this->factory_name = factory_name;
this->taste = taste;
}
string get_taste() {
return taste;
}
};
class Chocolate :public Snack {
string design;
public:
Chocolate(string money, string name, string factory_name, string design) {
this->money = money;
this->name = name;
this->factory_name = factory_name;
this->design = design;
}
string get_design() {
return design;
}
};
int main() {
Snack snackBasket[4] = { Candy("2800","초코비","짱구 주식회사","민초맛 사탕"),
Chocolate("3500", "석기시대","맹구 주식회사", "돌멩이모양"),
Candy("2800","돌사탕","짱구 주식회사","설탕맛 사탕"),
Chocolate("3500", "청포도","맹구 주식회사", "청포도모양") };
for (int i = 0; i < 4; i++) {
cout << snackBasket[i].get_name() << endl;
}
}
응용
class Snack {
protected:
string name;
string money;
string taste;
string factory_name;
};
class Candy :public Snack {
string smell;
public:
Candy(string money, string name, string factory_name, string taste) {
this->money = money;
this->name = name;
this->factory_name = factory_name;
this->taste = taste;
}
void candy() {
cout << "사탕 이름: " << name << "\n";
cout << "사탕의 가격: " << money << "\n";
cout << "맛: " << taste << "\n";
cout << "제조사: " << factory_name << "\n";
}
string get_smell(string smell) {
return smell;
}
};
class Chocolate :public Snack {
string design;
public:
Chocolate(string money, string name, string factory_name, string taste) {
this->money = money;
this->name = name;
this->factory_name = factory_name;
this->taste = taste;
}
void chocolate() {
cout << "초콜릿 이름: " << name << "\n";
cout << "초콜릿 가격: " << money << "\n";
cout << "맛: " << taste << "\n";
cout << "제조사: " << factory_name << "\n";
}
string get_design(string design) {
return design;
}
};
int main() {
string name, money, taste, factory_name;
string snack, design ,smell;
cout << "간식 종류: ";
cin >> snack;
//Chocolate choco; // (name, money, taste, factory_name);
if (snack == "초콜릿") {
cout << "초콜릿 이름: ";
cin >> name;
cout << "가격: ";
cin >> money;
cout << "맛: ";
cin >> taste;
cout << "제작사: ";
cin >> factory_name;
cout << "모양: ";
cin >> design;
cout << "---초콜릿 정보--- \n \n";
Chocolate choco(name, money, taste, factory_name);
cout << "초콜릿 모양: " << choco.get_design(design);
}
else if (snack == "사탕") {
cout << "사탕 이름: ";
cin >> name;
cout << "가격: ";
cin >> money;
cout << "맛: ";
cin >> taste;
cout << "제작사: ";
cin >> factory_name;
cout << "첨가된 향: ";
cin >> smell;
cout << "---사탕 정보--- \n \n";
Candy candy(name, money, taste, factory_name);
cout << "사탕의 향: " << candy.get_smell(smell);
}
else {
cout << "없는 정보!";
}
}
추상클래스
[특징]
[예시]
virtual void exmaple() = 0;
class Elec { //추상 클래스
public:
virtual void on() = 0; // 추상메소드
virtual void off() = 0;
};
class TV : public Elec{
//부모클래스에서 상속받은 순수가상함수(추상)를 구현하지 않을 경우,
//자식 클래스 또한 추상클래스가 된다.
//모든 순수가상함수를 구현 해줘야 한다.
public:
void on() {
cout << "TV On" << endl;
}
void off() {
cout << "TV Off" << endl;
}
// 일만 메소드가 있어도 추상메소드가 있으면 추상클래스이다.
void test() {
cout << "test" << endl;
}
};
class Radio :public Elec {
public:
void on() {
cout << "라디오 On" << endl;
}
void off() {
cout << "라디오 Off" << endl;
}
};
int main() {
//추상클래스로는 인스턴스(객체) 생성 불가
//Elec e;
//부모클래스에서 상속받은 순수가상함수(추상)를 구현하지 않을 경우,
//자식 클래스 또한 추상클래스가 된다.
//TV tv;
TV tv;
tv.on();
tv.off();
tv.test();
Radio rd;
rd.on();
rd.off();
}
실습 추상 클래스
(1) Shape 클래스를 상속받는 Circle, Rect, Tria를 구현해주세요
(2) 도형의 이름을 출력하는 draw() 메소드를 구현해주세요
class Shape {
protected:
virtual void draw() = 0;
};
class Circle :public Shape {
public:
void draw() {
cout << "동 투더 그 투더 라뮈~" << endl;
}
};
class Rect :public Shape {
public:
void draw() {
cout << "네모의 꿈" << endl;
}
};
class Tria :public Shape {
public:
void draw() {
cout << "ㅍㅣ라미드" << endl;
}
};
int main() {
string a;
cout << "원하는 도형의 모양을 입력해보세요 : ";
cin >> a;
while (1) {
if (a == "c") {
Circle c;
c.draw();
break;
}
else if (a == "r") {
Rect r;
r.draw();
break;
}
else if (a == "t") {
Tria t;
t.draw();
break;
}
else {
cout << "없는 도형입니다 다시 입력해주세영: ";
cin >> a;
}
}
}
소멸자
소멸자에 대해 간단히 알아보자
using namespace std;
//필드(변수), 메소드(함수), 생성자(메소드의 일종), 소멸자(메소드의 일종)
//소멸자
class Person {
int age;
string name;
int* p = new int[3];
public:
Person() { //생성자
cout << "생성자 실행 \n";
}
Person(string name) { //생성자
cout << "생성자 name 실행 \n";
}
void test() { // 메소드
cout << "test 실행 \n";
}
~Person() {// 소멸자: 객체가 생성된 만큼 실행
delete[] p;
cout << "소멸자 실행 \n";
}
};
class Student : public Person {
public:
~Student() {// 소멸자: 객체가 생성된 만큼 실행
cout << "스튜던트 소멸자 실행 \n";
}
};
int main() {
Person p("짱구");
p.test();
Person p1;
p1.test();
//p.~Person();//명시적으로 호출
//p1.~Person();//명시적으로 호출
//포인터 문법의 경우엔 명시적으로 호출을 해줘야 한다.
Person* p2 = new Person();
delete p2;
//Student소멸자 실행 후 Student에 상속받은 소멸자도 실행
Student s;
}
마무리
클래스에 대한 다형성과 추상클래스의 개념에 대해 알아보았돠!
자식클래스에서 부모클래스의 추상메소드를 상속받아 구현할 때, 모든 순수가상함수를 구현해줘야 된다는 것은 알고 있었지만 다시금 공부하지 않았다면,
언젠가 일반 메소드가 있다면 추상메소드가 있어도 일반 클래스이다?
이런식으로 헷갈렸을지 모를일이다.
이미 공부하고 알고있었던 지식이지만 완벽하게 숙지하고 있지 않은 부분들에 대해 다시금 개념을 공부하게 되는 것은 내가 인지하고 있지 못했던 부족한 점들을 일깨워 주는 것 같다.
예습만 할 것이 아니라 복습도 꾸준히 해야된다는 것을 느끼게 된다.