다중 상속 - 가상 상속 추상 자료형 순수 가상함수

Slides:



Advertisements
Similar presentations
3. C++와 객체지향 C++ 코딩 방법 객체 단위로 2 개의 파일 인터페이스 파일 구현파일
Advertisements

01_ 가상 함수를 사용한 다형성의 구현 02_ 오버라이딩
명품 C++ 프로그래밍 3장. 클래스와 객체.
명품 C++ 8장 상속.
컴퓨터 응용 및 실습 Part1. OOP&Java Programming data type Review
명품 C++ 4장. 객체 포인터와 객체 배열, 객체의 동적 생성.
C++ Espresso 제1장 기초 사항.
C++ Espresso 제2장 제어문과 함수.
강좌명 : C++프로그래밍 (C++ Programming)
제6장 객체배열과 벡터 객체 배열을 이해한다. 벡터(vector) 클래스를 사용할 수 있다.
C++ Exspresso 제5장 클래스의 기초.
2주 실습강의 Java의 기본문법(1) 인공지능연구실.
8. 객체와 클래스 (기본).
11장 구조체와 열거형 구조체의 정의 구조체 변수의 선언 구조체 초기화 및 사용 구조체 재정의 포인터를 이용해서 구조체 사용
윤 홍 란 다형성과 가상 함수 윤 홍 란
제12장 다형성과 가상함수 다형성의 개념을 이해한다. 상향 형변환의 개념을 이해한다. 가상 함수의 개념을 이해한다.
C++ Espresso 제9장 다형성.
명품 C++ 8장 상속.
명품 C++ 9장 가상 함수와 추상 클래스.
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
C++ Espresso 제6장 생성자와 소멸자.
8.1 인터페이스 개요와 인터페이스 정의 8.2 인터페이스의 사용 8.3 인터페이스의 상속 8.4 인터페이스 참조
상속이란? - 기반클래스로부터 다른 클래스를 파생하는 법 protected란? 가상함수 (virtual function)
명품 C++ 7장 프렌드와 연산자 중복.
C ++ 프로그래밍 시작.
정적 멤버 변수/정적 멤버 함수 - friend 함수/클래스 template
C++ Espresso 제12장 템플릿.
C++ Programming: chapter 7 – inheritence
제4장 클래스와 객체 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다.
23장. 구조체와 사용자 정의 자료형 2.
패키지와 접근 제어 패키지에 대하여 접근 제어에 대하여.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
배열이란? 배열의 선언? - 배열과 포인터의 관계? 문자열이란? 문자배열 연결 리스트
스택(Stack) 김진수
14. 예외처리.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
13. 연산자 오버로딩.
제14장 예외처리와 템플릿 예외 처리의 개요를 학습한다. 예외 처리를 적용할 수 있다. 템플릿의 개념을 이해한다.
제5장 생성자와 접근제어 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
명품 C++ 9장 가상 함수와 추상 클래스.
가상함수와 추상 클래스.
제2장 제어구조와 배열 if-else 문에 대하여 학습한다. 중첩 if-else 문에 대하여 학습한다.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
제 12장. 사용자 정의형으로서의 클래스 학기 프로그래밍언어및실습 (C++).
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Lab 8 Guide: 멀티스레딩 예제 2 * Critical Section을 이용한 멀티스레딩 동기화 (교재 15장, 쪽)
루프와 카운트 Looping and counting
C++ Espresso 제11장 예외 처리와 형변환.
멤버함수 중첩( 복사 생성자 ) - 연사자 중첩 - 동적 메모리를 가지는 클래스를 지원 하도록 멤버 함수 작성
제8장 포인터와 동적객체 생성 포인터의 개념을 이해한다. 포인터와 관련된 연산을 이해한다.
A Basic of C++.
12. 상속 : 고급.
조 병 규 Software Quality Lab. 한 국 교 통 대 학 교
제 11장. 템플릿과 STL 학기 프로그래밍언어및실습 (C++).
03. 메모리 관리 C++ 프로그램에서 다룰 수 있는 메모리의 종류
SelfShopping ProJect.
Chapter 2 C++ 함수와 네임스페이스. 최호성.
중복 멤버의 처리 조 병 규 한 국 교 통 대 학 교 SQ Lab..
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
서브클래스 조 병 규 한 국 교 통 대 학 교 SQ Lab..
자바 프로그래밍 Thread를 이용한 애니메이션 서울호서전문학교 게임프로그램개발과.
Static과 const 선언 조 병 규 한 국 교 통 대 학 교 SQ Lab..
실습과제 1번 /* 1. 멤버 변수로 반경 radius를 갖고, 그 값을 모니터에 출력하는
자바 객체 지향 프로그래밍 Ps lab 김윤경.
상속 (Inheritance) private 전용부분 전용부분 공용부분 공용부분 public 기본 클래스
7 생성자 함수.
발 표 자 : 7조 손 창 국 윤 오 성, 박 진 완 객체 지향 프로그래밍 C++
Presentation transcript:

다중 상속 - 가상 상속 추상 자료형 순수 가상함수 다형성 다중 상속 - 가상 상속 추상 자료형 순수 가상함수

Pegasus class의 지원 표유류 말 새 Pegasus ? 다중 상속 Pegasus class의 지원 말로 부터 파생 : Fly( ) 함수는 복사 말과 조류의 양쪽 목록에 등록할 수 없음 Fly( ) 함수가 두 군데에 존재 : 유지 보수 어려움 표유류 말 Gallop( ) Whinny( ) 새 Fly( ) Pegasus ? 다중 상속

상승 (Percolating Upward) 필요로 하는 함수( Fly( ) )를 한 단계 상위 클래스 계층으로 상승 상승 사용시의 원칙 공통되는 기능은 상승 몇 개의 파생클래스에서만 쓰는 접속 부분은 상승 시키지 않음

#include <iostream> using namespace std; class Horse { public: void Gallop(){ cout << "Galloping...\n"; } virtual void Fly() { cout << "Horses can't fly.\n" ; } private: int itsAge; }; class Pegasus : public Horse virtual void Fly() {cout<<"I can fly! I can fly! I can fly!\n";} list 14.1

const int NumberHorses = 5; int main() { Horse* Ranch[NumberHorses]; Horse* pHorse; int choice,i; for (i=0; i<NumberHorses; i++) cout << "(1)Horse (2)Pegasus: "; cin >> choice; if (choice == 2) pHorse = new Pegasus; else pHorse = new Horse; Ranch[i] = pHorse; } cout << "\n"; Ranch[i]->Fly(); delete Ranch[i]; return 0;

형 변환 하향 (casting down) RTTI ( Run Time Type Identification) 실행 시 형 식별 dynamic_cast < 형 > 변수명 변환이 적절한 경우 형변환 적절하지 않으면 널포인터로 채움

#include <iostream> using namespace std; enum TYPE { HORSE, PEGASUS }; class Horse { public: virtual void Gallop(){ cout << "Galloping...\n"; } private: int itsAge; }; class Pegasus : public Horse virtual void Fly() {cout<<"I can fly! I can fly! I can fly!\n";} list 14.2

const int NumberHorses = 5; int main() { Horse* Ranch[NumberHorses]; Horse* pHorse; int choice,i; for (i=0; i<NumberHorses; i++) cout << "(1)Horse (2)Pegasus: "; cin >> choice; if (choice == 2) pHorse = new Pegasus; else pHorse = new Horse; Ranch[i] = pHorse; } Pegasus *pPeg = dynamic_cast< Pegasus *> (Ranch[i]); if (pPeg) pPeg->Fly(); cout << "Just a horse\n"; delete Ranch[i]; return 0;

다중 상속 (Multiple Inheritance) 하나 이상의 기본 클래스로부터 파생 클래스를 만드는 것 각 기본 클래스를 쉼표로 분리 메모리에 만들어질 때 모든 기본 클래스가 파생 클래스를 구성하게 됨 class Pegasus : public Horse, public Bird Horse Bird Pegasus

#include <iostream> using namespace std; class Horse { public: Horse() { cout << "Horse constructor... "; } virtual ~Horse() { cout << "Horse destructor... "; } virtual void Whinny() const { cout << "Whinny!... "; } private: int itsAge; }; class Bird Bird() { cout << "Bird constructor... "; } virtual ~Bird() { cout << "Bird destructor... "; } virtual void Chirp() const { cout << "Chirp... "; } virtual void Fly() const cout << "I can fly! I can fly! I can fly! "; } int itsWeight; list 14.3

class Pegasus : public Horse, public Bird { public: void Chirp() const { Whinny(); } Pegasus() { cout << "Pegasus constructor... "; } ~Pegasus() { cout << "Pegasus destructor... "; } };

const int MagicNumber = 2; int main() { Horse* Ranch[MagicNumber]; Bird* Aviary[MagicNumber]; Horse * pHorse; Bird * pBird; int choice,i; for (i=0; i<MagicNumber; i++){ cout << "\n(1)Horse (2)Pegasus: "; cin >> choice; if (choice == 2) pHorse = new Pegasus; else pHorse = new Horse; Ranch[i] = pHorse; } cout << "\n(1)Bird (2)Pegasus: "; pBird = new Pegasus; pBird = new Bird; Aviary[i] = pBird;

cout << "\n"; for (i=0; i<MagicNumber; i++) { cout << "\nRanch[" << i << "]: " ; Ranch[i]->Whinny(); delete Ranch[i]; } cout << "\nAviary[" << i << "]: " ; Aviary[i]->Chirp(); Aviary[i]->Fly(); delete Aviary[i]; return 0;

#include <iostream> using namespace std; typedef int HANDS; enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ; class Horse { public: Horse(COLOR color, HANDS height); virtual ~Horse() { cout << "Horse destructor...\n"; } virtual void Whinny()const { cout << "Whinny!... "; } virtual HANDS GetHeight() const { return itsHeight; } virtual COLOR GetColor() const { return itsColor; } private: HANDS itsHeight; COLOR itsColor; }; Horse::Horse(COLOR color, HANDS height): itsColor(color),itsHeight(height) cout << "Horse constructor...\n"; } list 14.4

class Bird { public: Bird(COLOR color, bool migrates); virtual ~Bird() {cout << "Bird destructor...\n"; } virtual void Chirp()const { cout << "Chirp... "; } virtual void Fly()const cout << "I can fly! I can fly! I can fly! "; } virtual COLOR GetColor()const { return itsColor; } virtual bool GetMigration() const { return itsMigration; } private: COLOR itsColor; bool itsMigration; }; Bird::Bird(COLOR color, bool migrates): itsColor(color), itsMigration(migrates) cout << "Bird constructor...\n";

class Pegasus : public Horse, public Bird { public: void Chirp()const { Whinny(); } Pegasus(COLOR, HANDS, bool,long); ~Pegasus() {cout << "Pegasus destructor...\n";} virtual long GetNumberBelievers() const return itsNumberBelievers; } private: long itsNumberBelievers; }; Pegasus::Pegasus( COLOR aColor, HANDS height, bool migrates, long NumBelieve): Horse(aColor, height), Bird(aColor, migrates), itsNumberBelievers(NumBelieve) cout << "Pegasus constructor...\n";

int main() { Pegasus *pPeg = new Pegasus(Red, 5, true, 10); pPeg->Fly(); pPeg->Whinny(); cout << "\nYour Pegasus is " << pPeg->GetHeight(); cout << " hands tall and "; if (pPeg->GetMigration()) cout << "it does migrate."; else cout << "it does not migrate."; cout << "\nA total of " << pPeg->GetNumberBelievers(); cout << " people believe it exists.\n"; delete pPeg; return 0; }

다중 상속 (cont.) (X) (O) (X) 모호성 리스트 14.4에서 Horse와 Bird는 각각 자신만의 고유한 istColor 변수와 GetColor( )를 가짐 따라서, 상속 받은 Pegasus는 모호성을 가지게 됨 함수나 자료 앞에 기본 클래스 이름을 씀으로써 이를 해결 Pegasus에서 GetColor( ) 함수를 재생 COLOR currentColor = pPeg->GetColor( ); (X) COLOR currentColor = pPeg->Horse::GetColor( ); (O) virtual COLOR GetColor( ) const { return Horse :: itsColor;} (X)

가상 상속 Animal Animal Horse Bird Pegasus 공유된 기본 클래스로부터 상속

#include <iostream> using namespace std; typedef int HANDS; enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ; class Animal { public: Animal(int); virtual ~Animal() { cout << "Animal destructor...\n"; } virtual int GetAge() const { return itsAge; } virtual void SetAge(int age) { itsAge = age; } private: int itsAge; }; Animal::Animal(int age): itsAge(age) cout << "Animal constructor...\n"; } list 14.5

class Horse : public Animal { public: Horse(COLOR color, HANDS height, int age); virtual ~Horse() { cout << "Horse destructor...\n"; } virtual void Whinny() const { cout << "Whinny!... "; } virtual HANDS GetHeight() const { return itsHeight; } virtual COLOR GetColor() const { return itsColor; } protected: HANDS itsHeight; COLOR itsColor; }; Horse::Horse(COLOR color, HANDS height, int age): Animal(age), itsColor(color),itsHeight(height) cout << "Horse constructor...\n"; }

class Bird : public Animal { public: Bird(COLOR color, bool migrates, int age); virtual ~Bird() {cout << "Bird destructor...\n"; } virtual void Chirp() const { cout << "Chirp... "; } virtual void Fly() const { cout << "I can fly! I can fly! I can fly! "; } virtual COLOR GetColor() const { return itsColor; } virtual bool GetMigration() const { return itsMigration; } protected: COLOR itsColor; bool itsMigration; }; Bird::Bird(COLOR color, bool migrates, int age): Animal(age), itsColor(color), itsMigration(migrates) cout << "Bird constructor...\n"; }

class Pegasus : public Horse, public Bird { public: void Chirp() const { Whinny(); } Pegasus(COLOR, HANDS, bool, long, int); virtual ~Pegasus() {cout << "Pegasus destructor...\n";} virtual long GetNumberBelievers() const { return itsNumberBelievers; } virtual COLOR GetColor() const { return Horse::itsColor; } virtual int GetAge() const { return Horse::GetAge(); } private: long itsNumberBelievers; }; Pegasus::Pegasus( COLOR aColor, HANDS height, bool migrates, long NumBelieve, int age): Horse(aColor, height,age), Bird(aColor, migrates,age), itsNumberBelievers(NumBelieve) cout << "Pegasus constructor...\n"; }

int main() { Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2); int age = pPeg->GetAge(); cout << "This pegasus is " << age << " years old.\n"; delete pPeg; return 0; }

가상 상속 (cont.) Animal Horse Bird Pegasus 가상 상속 가상기본클래스 가상상속 가상상속 위의 그림과 같이 단일 공통 클래스 가능해짐 실질적인 변화는 Pegasus에서 발생 가상 기본 클래스를 사용할 때 가장 최근에 파생된 클래스로부터 공통 기본 클래스를 초기화 Animal은 Horse와 Bird로 초기화되지 않고 Pegasus의 것으로 초기화 가상기본클래스 Animal 가상상속 가상상속 Horse Bird Pegasus

#include <iostream> using namespace std; typedef int HANDS; enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ; class Animal { public: Animal(int); virtual ~Animal() { cout << "Animal destructor...\n"; } virtual int GetAge() const { return itsAge; } virtual void SetAge(int age) { itsAge = age; } private: int itsAge; }; Animal::Animal(int age): itsAge(age) cout << "Animal constructor...\n"; } list 14.6

class Horse : virtual public Animal { public: Horse(COLOR color, HANDS height, int age); virtual ~Horse() { cout << "Horse destructor...\n"; } virtual void Whinny() const { cout << "Whinny!... "; } virtual HANDS GetHeight() const { return itsHeight; } virtual COLOR GetColor() const { return itsColor; } protected: HANDS itsHeight; COLOR itsColor; }; Horse::Horse(COLOR color, HANDS height, int age): Animal(age), itsColor(color),itsHeight(height) cout << "Horse constructor...\n"; }

class Bird : virtual public Animal { public: Bird(COLOR color, bool migrates, int age); virtual ~Bird() {cout << "Bird destructor...\n"; } virtual void Chirp() const { cout << "Chirp... "; } virtual void Fly() const { cout << "I can fly! I can fly! I can fly! "; } virtual COLOR GetColor() const { return itsColor; } virtual bool GetMigration() const { return itsMigration; } protected: COLOR itsColor; bool itsMigration; }; Bird::Bird(COLOR color, bool migrates, int age): Animal(age), itsColor(color), itsMigration(migrates) cout << "Bird constructor...\n"; }

class Pegasus : public Horse, public Bird { public: void Chirp() const { Whinny(); } Pegasus(COLOR, HANDS, bool, long, int); virtual ~Pegasus() {cout << "Pegasus destructor...\n";} virtual long GetNumberBelievers() const { return itsNumberBelievers; } virtual COLOR GetColor() const { return Horse::itsColor; } // virtual int GetAge() const { return Horse::GetAge(); } private: long itsNumberBelievers; }; Pegasus::Pegasus( COLOR aColor, HANDS height, bool migrates, long NumBelieve, int age): Horse(aColor, height,age), Bird(aColor, migrates,age), Animal(age*2), itsNumberBelievers(NumBelieve) cout << "Pegasus constructor...\n"; }

int main() { Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2); int age = pPeg->GetAge(); cout << "This pegasus is " << age << " years old.\n"; delete pPeg; return 0; }

추상 자료형 (Abstract Data Type) 자신으로부터 파생된 클래스에게 인터페이스만 제공하기 위해 존재 객체를 나타내기 보다는 개념을 나타냄 항상 다른 클래스에 대한 기본 클래스로 사용 추상 자료형의 객체를 만들 수 없음 순수가상함수가 하나라도 존재하는 클래스 순수가상함수 가상함수를 0으로 초기화 하나 이상의 순수가상함수를 가진 클래스는 추상 자료형 추상자료 형으로부터 파생된 모든 클래스는 순수가상함수를 그대로 상속함. 따라서, 객체를 실체화하는 방법은 오직 순수가상함수의 재생을 통해서만 가능 virtual void Draw( ) = 0; 순수가상함수를 가진 클래스는 객체를 만들지 말 것 순수가상함수는 재생하여 사용할 것

#include <iostream> using std::cout; using std::cin; using std::endl; class Shape { public: Shape(){} virtual ~Shape(){} virtual long GetArea() { return -1; } // error virtual long GetPerim() { return -1; } virtual void Draw() {} private: }; list 14.7

class Circle : public Shape { public: Circle(int radius):itsRadius(radius){} ~Circle(){} long GetArea() { return 3 * itsRadius * itsRadius; } long GetPerim() { return 6 * itsRadius; } void Draw(); private: int itsRadius; int itsCircumference; }; void Circle::Draw() cout << "Circle drawing routine here!\n"; }

class Rectangle : public Shape { public: Rectangle(int len, int width): itsLength(len), itsWidth(width){} virtual ~Rectangle(){} virtual long GetArea() { return itsLength * itsWidth; } virtual long GetPerim() {return 2*itsLength + 2*itsWidth; } virtual int GetLength() { return itsLength; } virtual int GetWidth() { return itsWidth; } virtual void Draw(); private: int itsWidth; int itsLength; }; void Rectangle::Draw() for (int i = 0 ; i<itsLength ; i++) for (int j = 0 ; j<itsWidth ; j++) cout << "x "; cout << "\n"; }

class Square : public Rectangle { public: Square(int len); Square(int len, int width); ~Square(){ } long GetPerim() {return 4 * GetLength();} }; Square::Square(int len): Rectangle(len,len) { } Square::Square(int len, int width): Rectangle(len,width) if (GetLength() != GetWidth()) cout << "Error, not a square... a Rectangle??\n"; }

int main() { int choice; bool fQuit = false; Shape * sp; while ( !fQuit ){ cout << "(1)Circle (2)Rect (3)Square (0)Quit: "; cin >> choice; switch (choice){ case 0: fQuit = true; break; case 1: sp = new Circle(5); case 2: sp = new Rectangle(4,6); case 3: sp = new Square(5); default: cout<<"Please enter a number(0~3)\n” continue; break; } if( !fQuit ) sp->Draw(); delete sp; sp = 0; cout << "\n"; return 0;

세 개의 순수가상함수를 모두 재정의 해야만 객체를 class Shape { public: Shape(){} ~Shape(){} virtual long GetArea() = 0; // error virtual long GetPerim()= 0; virtual void Draw() = 0; private: }; list 14.8 세 개의 순수가상함수를 모두 재정의 해야만 객체를 만들 수 있음

기타-순수가상함수 Animal Mammal Dog 순수가상함수의 구현 가능 추상의 복합 계층 추상 자료형의 순수가상함수는 파생 객체에 의해 호출 가능 재정의된 함수들에게 공통 기능 부여를 위해 주로 이용 추상의 복합 계층 하나의 추상자료형에서 다른 추상자료형의 파생 가능 Animal ABT 가상함수 Eat( ), Sleep( ), Move( ), Reproduce( ) Reproduce( ) 재정의 Mammal ABT 가상함수 Eat( ), Sleep( ), Move( ) Eat( ), Sleep( ), Move( ) 재정의 Dog 객체가능

#include <iostream> using namespace std; class Shape { public: virtual ~Shape(){ } virtual long GetArea() = 0; virtual long GetPerim()= 0; virtual void Draw() = 0; private: }; void Shape::Draw() cout << "Abstract drawing mechanism!\n"; } list 14.9

class Circle : public Shape { public: Circle(int radius):itsRadius(radius){ } virtual ~Circle(){ } long GetArea() { return 3 * itsRadius * itsRadius; } long GetPerim() { return 9 * itsRadius; } void Draw(); private: int itsRadius; int itsCircumference; }; void Circle::Draw() cout << "Circle drawing routine here!\n"; Shape::Draw(); }

class Rectangle : public Shape { public: Rectangle(int len, int width): itsLength(len), itsWidth(width){ } virtual ~Rectangle(){} long GetArea() { return itsLength * itsWidth; } long GetPerim() {return 2*itsLength + 2*itsWidth; } virtual int GetLength() { return itsLength; } virtual int GetWidth() { return itsWidth; } void Draw(); private: int itsWidth; int itsLength; }; void Rectangle::Draw() for (int i = 0; i<itsLength; i++) for (int j = 0; j<itsWidth; j++) cout << "x "; cout << "\n"; } Shape::Draw();

class Square : public Rectangle { public: Square(int len); Square(int len, int width); virtual ~Square(){ } long GetPerim() {return 4 * GetLength();} }; Square::Square(int len): Rectangle(len,len) { } Square::Square(int len, int width): Rectangle(len,width) if (GetLength() != GetWidth()) cout << "Error, not a square... a Rectangle??\n"; }

int main() { int choice; bool fQuit = false; Shape * sp; while ( !fQuit ){ cout << "(1)Circle (2)Rect (3)Square (0)Quit: "; cin >> choice; switch (choice){ case 0: fQuit = true; break; case 1: sp = new Circle(5); case 2: sp = new Rectangle(4,6); case 3: sp = new Square(5); default: cout<<"Please enter a number(0~3)\n” continue; break; } if( !fQuit ) sp->Draw(); delete sp; sp = 0; cout << "\n"; return 0;