728x90
728x90
outline
Pointer, References and Inheritance
Virtual Function
Virtual Destructor
Caution : Object Slicing
C++에서 다형성(Polymorphism in C++)
- 같은 함수 호출에 대해 서로 다른 방법으로 응답을 하는 것을 객체지향에서 다형성이라 한다.
포인트, 주소 그리고 상속(Pointers, References and Inheritance)
- C++에서 다형성을 사용하기 전에, 상속에서 포인터와 주소 연산이 어떻게 사용되는지 이해가 필요하다.
#include <iostream>
using namespace std;
class Person {
public:
void Talk() {
cout << "talk" << endl;
}
};
class Student : public Person {
public:
void Study() {
cout << "study" << endl;
}
};
class CSStudent : public Student {
public:
void WriteCode() {
cout << "write_code" << endl;
}
};
C -> B -> A
상속에서 포인터(Pointers with Inheritance)
-
기본 클래스(base class) B의 포인터는 B 클래스의 주소를 저장할 수 있다.
-
기본 클래스(base class) B의 포인터는 파생 클래스(derived class) C의 주소를 저장할 수 있다.
-
기본 클래스(base class) B의 포인터는 기본 클래스 A의 상위 개체의 주소를 저장할 수 없다.
-
C는 B이다, 그러나 A는 B가 아니다.
int main() {
Person* p1 = new Person;
Person* p2 = new Student;
Person* p3 = new CSStudent;
Student* s1 = new Person; // error
Student* s2 = new Student;
Student* s3 = new CSStudent;
delete p1;
delete p2;
delete p3;
delete s1;
delete s2;
delete s3;
return 0;
}
int main() {
Student st;
Person* person_st = &st; // ok
Student* student_st = &st; // ok
CSStudent* csstudent_st = &st; //error!
CSStudent csst;
Person* person_csst = &csst; // ok
Student* student_csst = &csst; // ok
CSStudent* csstudent_csst = &csst; //ok
return 0;
}
-
파생 클래스 B의 포인터는 부모 클래스 A의 member에 접근할 수 있다.
-
파생 클래스 B의 포인터는 파생 클래스 B의 member에 접근할 수 있다.
-
파생 클래스 B의 포인터는 자식 클래스 C의 member에 절대 접근할 수 없다.
int main() {
Student st;
Person* person_st = &st;
Student& student_st = st;
person_st->Talk();
person_st->Study(); // error!
person_st->WriteCode(); // error!
student_st->Talk();
student_st->Study();
student_st->WriteCode(); // error!
return 0;
}
상속에서 주소연산(References with Inheritance)
-
기본 클래스 B의 reference는 기본 클래스 B의 객체를 언급할 수 있다.
-
기본 클래스 B의 reference는 자식 클래스 C의 객체를 언급할 수 있다.
-
기본 클래스 B의 reference는 부모 클래스 A의 객체를 절대 언급할 수 없다.
int main() {
Student st;
Person& person_st = st; // ok
Student& student_st = st; // ok
CSStudent& csstudent_st = st; //error!
CSStudent csst;
Person& person_csst = csst; // ok
Student& student_csst = csst; // ok
CSStudent& csstudent_csst = csst; //ok
return 0;
}
-
파생 클래스 B의 reference는 부모 클래스 A의 멤버에 접근할 수 있다.
-
파생 클래스 B의 reference는 파생 클래스 B의 멤버에 접근할 수 있다.
-
파생 클래스 B의 reference는 자식 클래스 C의 멤버에 절대 접근할 수 없다.
int main() {
Student st;
Person& person_st = st;
Student& student_st = st;
person_st.Talk();
person_st.Study(); // error!
person_st.WriteCode(); // error!
student_st.Talk();
student_st.Study();
student_st.WriteCode(); // error!
return 0;
}
추상 함수(Virtual Functions)
- 함수의 선언한 부분만 있고 구현 부분이 없는 함수를 말한다. 선언된 추상 클래스는 하위 클래스에서 구현되는데, 각각의 하위 클래스에서 상속받은 추상 함수를 서로 다른 방법으로 구현할 수 있다.
// Vehicle classes.
class Vehicle {
public:
virtual void Accelerate() {
cout << "Vehicle.Accelerate";
}
};
class Car : public Vehicle {
public:
virtual void Accelerate() {
cout << "Car.Accelerate";
}
};
class Truck : public Vehicle {
public:
virtual void Accelerate();
cout << "Truck.Accelerate";
}
};
// Main routine.
int main() {
Car car;
Truck truck;
Vehicle* pv = &car;
pv->Accelerate();
// Outputs Car.Accelerate.
pv = &truck;
pv->Accelerate();
// Outputs Truck.Accelerate.
Vehicle vehicle;
pv = &vehicle;
pv->Accelerate();
// Outputs Vehicle.Accelerate.
return 0;
}
추상 소멸자(Virtual Destructor)
class A {
public:
A() { cout << " A"; }
virtual ~A() { cout << " ~A"; }
};
class AA : public A {
public:
AA() { cout << " AA"; }
virtual ~AA() { cout << " ~AA"; }
};
int main() {
A* pa = new AA; // OK: prints ' A AA'.
delete pa; // OK: prints ' ~AA ~A'.
return 0;
}
- 추상 소멸자를 사용하지 않는다면, pa를 삭제(delete)할 때 단순히 A 클래스에서만 소멸(destructor)이 발생된다. 이런 문제가 발생이 된다면 메모리 부족(memory leak) 현상을 일으킬 수 있다. 추상 소멸자를 사용함으로써 컴파일러에게 추상 함수가 존재하는 것을 알려줄 수 있다.
object slicing
-
상속받은 클래스의 인스턴스를 부모 클래스의 인스턴스로 복사함으로써 상속받은 클래스가 가지고 있던 정보가 손실되는 것을 말한다.
class Base { int x, y; };
class Derived : public Base { int z, w; };
int main() {
Derived d;
Base b = d; // Object Slicing, z and w of d are sliced off
}
- 위에 예시를 보면 클래스 d안에 멤버는 x, y, w, z가 존재한다. 이 상태에서 x, y 멤버만 존재하는 클래스 b에 단순히 d를 복사를 한다면 저장할 공간이 없어서 w, z의 정보가 손실이 된다.
728x90
728x90
'Language > C++' 카테고리의 다른 글
[C++] 복사 생성자, 연산자 오버로딩(Copy Constructor, Operator Overloading)- 컴도리돌이 (0) | 2020.12.31 |
---|---|
[C++] 템플릿(Template) - 컴도리돌이 (0) | 2020.12.30 |
[C++] 상속(Inheritance) - 컴도리돌이 (0) | 2020.12.27 |
[C++] 이중 연결 리스트 (Double Linked List) - 컴도리돌이 (0) | 2020.10.28 |
[C++] 연결리스트 (list.h , node.h , CMakeLists.txt)-컴도리돌이 (0) | 2020.10.27 |