Download presentation
Presentation is loading. Please wait.
Published byTheodore Maxwell Modified 6년 전
1
상속이란? - 기반클래스로부터 다른 클래스를 파생하는 법 protected란? 가상함수 (virtual function)
2
상속이란? Animal Mammal Reptile Horse Dog 상속 파생
각 개념들간의 계층 구조에서 상위 개념(표유류)의 일반적인 특성을 하위 개념(개)이 이어 받는 것 계층 구조는 “한 종류”라는 식으로 표현 : 도요타는 차의 한 종류 파생 상위 클래스(기반/기본 클래스, 부모 클래스, base class)에서 새로운 특성을 추가하여 새로운 클래스(파생 클래스, derived class, child class)를 만드는 것 Animal Mammal Reptile Horse Dog
3
파생 구문 파생 클래스가 어디로부터 파생하였는지를 표시 class 파생클래스명 : 파생의형 기반클래스명
기반 클래스는 이전에 선언되어 있어야 함 파생 클래스는 기반 클래스의 생성자, 소멸자, friend 함수를 제외한 모든 것을 상속 class 파생클래스명 : 파생의형 기반클래스명 class Dog : public Mammal
4
#include <iostream> using namespace std;
enum BREED { GOLDEN, CAIRN, DANDIE}; class Mammal { public: Mammal(); ~Mammal(); int GetAge() const; void SetAge(int); int GetWeight() const; void SetWeight(); void Speak() const; void Sleep() const; protected: int itsAge; int itsWeight; }; list 12.1
5
class Dog : public Mammal
{ public: Dog(); ~Dog(); BREED GetBreed() const; void SetBreed(BREED); WagTail(); BegForFood(); protected: BREED itsBreed; };
6
전용(private) vs. 보호(protected)
(기반 클래스) public 파생된 클래스 : 접근 가능 기반 & 파생 클래스 외부 : 접근 가능 (기반 클래스) private 파생된 클래스 : 접근 불능 기반 & 파생 클래스 외부 : 접근 불능 (기반 클래스) protected
7
#include <iostream> using std::cout;
enum BREED { GOLDEN, CAIRN, DANDIE}; class Mammal { public: Mammal():itsAge(2), itsWeight(5){} ~Mammal(){} int GetAge() const { return itsAge; } void SetAge(int age) { itsAge = age; } int GetWeight() const { return itsWeight; } void SetWeight(int weight) { itsWeight = weight; } void Speak()const { cout << "Mammal sound!\n"; } void Sleep()const { cout << "shhh. I'm sleeping.\n"; } protected: int itsAge; int itsWeight; }; list 12.2
8
class Dog : public Mammal
{ public: Dog():itsBreed(GOLDEN){} ~Dog(){} BREED GetBreed() const { return itsBreed; } void SetBreed(BREED breed) { itsBreed = breed; } void WagTail() const { cout << "Tail wagging...\n"; } void BegForFood() const { cout << "Begging for food...\n"; } private: BREED itsBreed; }; int main() Dog fido; fido.Speak(); fido.WagTail(); cout << "Fido is " << fido.GetAge() << " years old\n"; return 0; }
9
class Parent { public: int b; void f(){a=1;} private: int a; }; class Child : public Parent void g(){ a=1; // (1) b=1; // (2) f(); // (3) } int c; int main() Child Tom; Tom.b = 3; // (4) Tom.a = 4; // (5) Tom.c = 5; // (6)
10
class Parent { public: int b; void f(){a=1;} protected: int a; }; class Child : public Parent void g(){ a=1; // (1) b=1; // (2) f(); // (3) } private: int c; int main() Child Tom; Tom.b = 3; // (4) Tom.a = 4; // (5) Tom.c = 5; // (6)
11
상속에서의 생성자와 소멸자 파생 클래스의 객체 생성 시 : 생성자 파생 클래스의 객체 소멸 시 : 소멸자
기반 클래스의 생성자 호출 파생 클래스의 생성자 호출 파생 클래스의 객체 소멸 시 : 소멸자 파생 클래스의 소멸자 호출 기반 클래스의 소멸자 호출 각각의 부분을 생성하고 소멸 시킴 기반 클래스의 생성자에게 인자 전달 기반 클래스의 생성자가 중첩되어 있는 경우 파생 클래스의 생성자 함수에서 기반 클래스의 생성자 함수 호출 기본 생성자 이외의 기반 클래스 생성자 실행 가능
12
#include <iostream> using namespace std;
enum BREED { GOLDEN, CAIRN, DANDIE}; class Mammal { public: Mammal(); Mammal(int age); ~Mammal(); int GetAge() const { return itsAge; } void SetAge(int age) { itsAge = age; } int GetWeight() const { return itsWeight; } void SetWeight(int weight) { itsWeight = weight; } void Speak() const { cout << "Mammal sound!\n"; } void Sleep() const { cout << "shhh. I'm sleeping.\n"; } protected: int itsAge; int itsWeight; }; list 12.4
13
class Dog : public Mammal
{ public: Dog(); Dog(int age); Dog(int age, int weight); Dog(int age, BREED breed); Dog(int age, int weight, BREED breed); ~Dog(); BREED GetBreed() const { return itsBreed; } void SetBreed(BREED breed) { itsBreed = breed; } void WagTail() const { cout << "Tail wagging...\n"; } void BegForFood() const { cout << "Begging for food...\n"; } private: BREED itsBreed; };
14
Mammal::Mammal(): itsAge(1), itsWeight(5)
{ cout << "Mammal constructor...\n"; } Mammal::Mammal(int age): itsAge(age), itsWeight(5) cout << "Mammal(int) constructor...\n"; Mammal::~Mammal() cout << "Mammal destructor...\n";
15
(X) Dog::Dog(): Mammal(), itsBreed(GOLDEN) {
cout << "Dog constructor...\n"; } Dog::Dog(int age): Mammal(age), itsBreed(GOLDEN) cout << "Dog(int) constructor...\n"; Dog::Dog(int age, int weight): Mammal(age), itsBreed(GOLDEN) itsWeight = weight; cout << "Dog(int, int) constructor...\n"; Dog::Dog(int age, int weight, BREED breed): Mammal(age), itsBreed(breed) cout << "Dog(int, int, BREED) constructor...\n"; ,itsWeight(weight) (X)
16
Dog::Dog(int age, BREED breed):
Mammal(age), itsBreed(breed) { cout << "Dog(int, BREED) constructor...\n"; } Dog::~Dog() cout << "Dog destructor...\n"; int main() Dog fido; Dog rover(5); Dog buster(6,8); Dog yorkie (3,GOLDEN); Dog dobbie (4,20,DOBERMAN); fido.Speak(); rover.WagTail(); cout << "Yorkie is " << yorkie.GetAge() << " years old\n"; cout << "Dobbie weighs "; cout << dobbie.GetWeight() << " pounds\n"; return 0;
17
함수 재정의/재생 (Overriding Function)
파생 클래스에서 기반 클래스의 함수 구현부를 새로이 만드는 것 함수의 반환 형, 원형부가 일치해야 함 함수 반환형 매개 변수의 목록 상수형 함수 표시 기반 클래스의 하나의 함수를 재정의하면 동일한 이름을 가진 모든 기반 클래스의 함수(중첩된 모든 기반 클래스의 함수)를 은폐 시키게 됨 기반 클래스의 함수가 재정의 되었더라도 함수의 이름을 완전하게 다 써주면 호출할 수 있음 파생클래스의객체명.기반클래스명::함수명( ) 중첩, 다중정의 (Overloading) vs. 재정의, 재생(Overriding)
18
#include <iostream> using namespace std; class Mammal { public:
void Move() const { cout << "Mammal move one step\n"; } void Move(int distance) const cout << "Mammal move " << distance; cout << " steps.\n"; } protected: int itsAge; int itsWeight; }; list 12.7
19
class Dog : public Mammal
{ public: void Move() const; }; void Dog::Move() const cout << "In dog move...\n"; Mammal::Move(3); } int main() Mammal bigAnimal; Dog fido; bigAnimal.Move(); bigAnimal.Move(2); fido.Move( ); fido.Move(6); fido.Mammal::Move(6); fido.Mammal::Move( ); return 0;
20
가상 메소드/함수 (Virtual Method)
기반클래스를 가리키는 포인터에 파생 클래스의 포인터를 대입하는 다형성(polymorphism) 지원 Dog는 Mammal의 한 종류이므로 가능 반대는 불가능 pMammal 포인터를 이용해 Mammal의 멤버 함수 호출 가능 Dog의 멤버 함수를 호출하려면? Mammal *pMammal = new Dog 가상 함수 기반 클래스의 함수를 가상함수로 만듦 virtual 반환형 함수명( 매개변수 리스트 )
21
#include <iostream> using std::cout; class Mammal { public:
Mammal():itsAge(1) { cout << "Mammal constructor...\n"; } virtual ~Mammal() { cout << "Mammal destructor...\n"; } void Move() const { cout << "Mammal move one step\n"; } virtual void Speak() const { cout << "Mammal speak!\n"; } protected: int itsAge; }; list 12.8
22
class Dog : public Mammal
{ public: Dog() { cout << "Dog Constructor...\n"; } virtual ~Dog() { cout << "Dog destructor...\n"; } void WagTail() { cout << "Wagging Tail...\n"; } void Speak() const { cout << "Woof!\n"; } void Move() const { cout << "Dog moves 5 steps...\n"; } }; int main() Mammal *pDog = new Dog; pDog->Move(); pDog->Speak(); pDog->WagTail(); Dog *ptemp = new Mammal; return 0; }
23
#include <iostream> using namespace std; class Mammal { public:
Mammal():itsAge(1) { } virtual ~Mammal() { } virtual void Speak() const { cout << "Mammal speak!\n"; } protected: int itsAge; }; list 12.9
24
class Dog : public Mammal
{ public: void Speak() const { cout << "Woof!\n"; } }; class Cat : public Mammal void Speak() const { cout << "Meow!\n"; } class Horse : public Mammal void Speak() const { cout << "Winnie!\n"; } class Pig : public Mammal void Speak() const { cout << "Oink!\n"; }
25
int main() { Mammal* theArray[5]; Mammal* ptr; int choice, i; for ( i = 0 ; i<5 ; i++ ) cout << "(1)dog (2)cat (3)horse (4)pig: "; cin >> choice; switch (choice) case 1: ptr = new Dog; break; case 2: ptr = new Cat; case 3: ptr = new Horse; case 4: ptr = new Pig; default: ptr = new Mammal; } theArray[i] = ptr; for ( i=0 ; i<5 ; i++ ) theArray[i]->Speak(); return 0;
26
다형성(polymorphism) 하나의 이름을 두 개 또는 그 이상의 관련된 목적에 사용할 수 있도록 하는 성질
함수 중첩 기반 클래스의 포인터에 파생 클래스의 포인터 대입 가능 기본 클래스에서 멤버 함수를 가상으로 만들었을 경우 파생 클래스에서도 가상으로 하여야 하는가? 역시 가상으로 되어 있지만 하는 것이 이해하기 좋음 하나의 이름을 두 개 또는 그 이상의 관련된 목적에 사용할 수 있도록 하는 성질
27
가상함수의 동작 원리 동적 바인딩(dynamic binding) 실행 바인딩(run-time binding)
가상함수를 위해서는 동적 바인딩 필요 가상함수가 존재하는 class의 객체가 만들어지면 객체는 그 함수를 추적해야 함 컴파일러는 가상함수테이블(virtual function table, v-table)을 만듦 각각의 파생 객체는 가상 테이블의 포인터 (vptr)를 유지하여야 함 동적 바인딩(dynamic binding) 실행 바인딩(run-time binding) 정적(static binding) 컴파일 바인딩(compile binding)
28
가상함수의 동작원리 (cont.) VPTR &Move( ) &Speak( ) Mammal VPTR Mammal
Mammal의 v-table Dog의 v-table VPTR &Move( ) &Speak( ) Mammal VPTR Mammal &Mammal:Move( ) &Dog:Speak( ) Dog Mammal을 가리키는 포인터가 사용되더라도 vptr은 객체의 실제형에 대한 함수를 가리키고 있음
29
기타 포인터와 참조자를 사용하는 경우 이러한 동작 가능 객체를 값으로 전달 시 가상함수 호출 되게 할 수 없음
30
#include <iostream> class Mammal { public:
Mammal():itsAge(1) { } virtual ~Mammal() { } virtual void Speak() const { std::cout << "Mammal speak!\n"; } protected: int itsAge; }; class Dog : public Mammal void Speak() const { std::cout << "Woof!\n"; } class Cat : public Mammal void Speak() const { std::cout << "Meow!\n"; } list 12.10
31
void ValueFunction (Mammal MammalValue)
{ MammalValue.Speak(); } void PtrFunction (Mammal * pMammal) pMammal->Speak(); void RefFunction (Mammal & rMammal) rMammal.Speak();
32
int main() { Mammal* ptr=0; int choice; ptr = new Cat; PtrFunction(ptr); RefFunction(*ptr); ValueFunction(*ptr); delete ptr; ptr = new Dog; return 0; }
33
가상 소멸자(virtual destructor)
기본클래스에서 가상인 함수가 있으면 그 소멸자도 가상이어야 한다 기본클래스의 소멸자가 가상이면 파생클래스의 소멸자가 호출
34
가상 복사 생성자 (Virtual Copy Constructor)
생성자는 가상이 될 수 없으므로 가상 복사 생성자는 없음 실질적인 복사를 수행한 후 복사된 객체에 대한 포인터를 반환 기반 클래스에서 Clone( ) 메소드를 가상으로 만듦
35
#include <iostream> using namespace std; class Mammal { public:
Mammal():itsAge(1) { cout << "Mammal constructor...\n"; } virtual ~Mammal() { cout << "Mammal destructor...\n"; } Mammal (const Mammal & rhs); virtual void Speak() const { cout << "Mammal speak!\n"; } virtual Mammal* Clone() { return new Mammal(*this); } int GetAge() const { return itsAge; } protected: int itsAge; }; Mammal::Mammal (const Mammal & rhs): itsAge(rhs.GetAge()) cout << "Mammal Copy Constructor...\n"; } list 12.11
36
class Dog : public Mammal
{ public: Dog() { cout << "Dog constructor...\n"; } virtual ~Dog() { cout << "Dog destructor...\n"; } Dog (const Dog & rhs); void Speak()const { cout << "Woof!\n"; } virtual Mammal* Clone() { return new Dog(*this); } }; Dog::Dog(const Dog & rhs): Mammal(rhs) cout << "Dog copy constructor...\n"; }
37
class Cat : public Mammal
{ public: Cat() { cout << "Cat constructor...\n"; } ~Cat() { cout << "Cat destructor...\n"; } Cat (const Cat &); void Speak()const { cout << "Meow!\n"; } virtual Mammal* Clone() { return new Cat(*this); } }; Cat::Cat(const Cat & rhs): Mammal(rhs) cout << "Cat copy constructor...\n"; }
38
enum ANIMALS { MAMMAL, DOG, CAT};
const int NumAnimalTypes = 3; int main() { Mammal *theArray[NumAnimalTypes]; Mammal* ptr; int choice, i; for ( i = 0; i<NumAnimalTypes; i++) cout << "(1)dog (2)cat (3)Mammal: "; cin >> choice; switch (choice) case DOG: ptr = new Dog; break; case CAT: ptr = new Cat; default: ptr = new Mammal; } theArray[i] = ptr;
39
Mammal *OtherArray[NumAnimalTypes];
for (i=0;i<NumAnimalTypes;i++) { theArray[i]->Speak(); OtherArray[i] = theArray[i]->Clone(); } OtherArray[i]->Speak(); return 0;
Similar presentations