윤 홍 란 hryun@sookmyung.ac.kr 다형성과 가상 함수 윤 홍 란 hryun@sookmyung.ac.kr.

Slides:



Advertisements
Similar presentations
3. 메소드와 변수 SCJP 자격증 프로젝트 발표자 : 최선웅. 1. 메 소 드 개 념 2. 메 소 드 양 식 3. 메 소 드 변 수 4. 메 소 드 예 제 5. 참 고 문 헌 / 자 료 목 차.
Advertisements

01_ 가상 함수를 사용한 다형성의 구현 02_ 오버라이딩
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
ㅎㅎ 구조체 C++ 프로그래밍 기초 : 객체지향의 시작 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스
C++ Espresso 제3장 배열과 포인터.
ㅎㅎ C++ 프로그래밍의 첫 걸음 C++로 프로그래밍한다는 것의 의미 세상에서 가장 간단한 C++ 프로그램
Chap07 상속 Section 1 : 상속의 개요 Section 2 : 멤버 변수의 상속
최윤정 Java 프로그래밍 클래스 상속 최윤정
연결리스트(linked list).
컴퓨터 프로그래밍 기초 [Final] 기말고사
제6장 객체배열과 벡터 객체 배열을 이해한다. 벡터(vector) 클래스를 사용할 수 있다.
제12장 다형성과 가상함수 다형성의 개념을 이해한다. 상향 형변환의 개념을 이해한다. 가상 함수의 개념을 이해한다.
C++ Espresso 제9장 다형성.
명품 C++ 9장 가상 함수와 추상 클래스.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
8.1 인터페이스 개요와 인터페이스 정의 8.2 인터페이스의 사용 8.3 인터페이스의 상속 8.4 인터페이스 참조
제 3장. C보다 나은 C++ II.
1. C++ 시작하기.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
정적 멤버 변수/정적 멤버 함수 - friend 함수/클래스 template
C++ Espresso 제12장 템플릿.
자바 5.0 프로그래밍.
제4장 클래스와 객체 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다.
패키지와 접근 제어 패키지에 대하여 접근 제어에 대하여.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
Lesson 7. 클래스와 메소드 - 1.
14. 예외처리.
10장. 예외처리.
자바 5.0 프로그래밍.
11장. 1차원 배열.
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
13. 연산자 오버로딩.
제14장 예외처리와 템플릿 예외 처리의 개요를 학습한다. 예외 처리를 적용할 수 있다. 템플릿의 개념을 이해한다.
7장 인터페이스와 추상 클래스.
Method & library.
자바 5.0 프로그래밍.
자바응용.
제5장 생성자와 접근제어 객체 지향 기법을 이해한다. 클래스를 작성할 수 있다. 클래스에서 객체를 생성할 수 있다.
27장. 모듈화 프로그래밍.
명품 C++ 9장 가상 함수와 추상 클래스.
가상함수와 추상 클래스.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
19. 함수 포인터와 void 포인터.
Lesson 2. 기본 데이터형.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
15장 컬렉션 프레임워크 Section 1 컬렉션 프레임워크의 개요 Section 2 리스트 Section 3 셋
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
제 4장. 객체 지향 프로그래밍 시작하기 학기 프로그래밍언어및실습 (C++).
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
제8장 포인터와 동적객체 생성 포인터의 개념을 이해한다. 포인터와 관련된 연산을 이해한다.
12. 상속 : 고급.
객체기반 SW설계 팀활동지 4.
제 11장. 템플릿과 STL 학기 프로그래밍언어및실습 (C++).
Chapter 13. 템플릿(Template) 1
Chapter 2 C++ 함수와 네임스페이스. 최호성.
클래스 : 기능 CHAPTER 7 Section 1 생성자(Constructor)
중복 멤버의 처리 조 병 규 한 국 교 통 대 학 교 SQ Lab..
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
3. 모듈 (5장. 모듈).
함수, 모듈.
Static과 const 선언 조 병 규 한 국 교 통 대 학 교 SQ Lab..
실습과제 1번 /* 1. 멤버 변수로 반경 radius를 갖고, 그 값을 모니터에 출력하는
1. 지역변수와 전역변수 2. auto, register 3. static,extern 4. 도움말 사용법
29장. 템플릿과 STL 01_ 템플릿 02_ STL.
어서와 C언어는 처음이지 제21장.
상속 (Inheritance) private 전용부분 전용부분 공용부분 공용부분 public 기본 클래스
7 생성자 함수.
6 객체.
Presentation transcript:

윤 홍 란 hryun@sookmyung.ac.kr 다형성과 가상 함수 윤 홍 란 hryun@sookmyung.ac.kr

Shape 클래스와 자식 클래스들(1) Shape클래스 // 일반적인 '도형'을 상징하는 클래스 class Shape { public: void Move(double x, double y); void Draw() const; Shape(); Shape(double x, double y); protected: double _x, _y; }; void Shape::Draw() const cout << "[Shape] Position = ( " << _x << ", " << _y << ")\n"; } 도형 원 사각형 삼각형

Shape 클래스와 자식 클래스들(2) Rectangle클래스 // 사각형을 상징하는 클래스 class Rectangle : public Shape { public: void Draw() const; void Resize(double width, double height); Rectangle(); Rectangle(double x, double y, double width, double height); protected: double _width; double _height; }; void Rectangle::Draw() const cout << "[Rectangle] Position = ( " << _x << ", " << _y << ") " "Size = ( " << _width << ", " << _height << ")\n"; }

Shape 클래스와 자식 클래스들(3) Circle 클래스 // 원을 상징하는 클래스 class Circle : public Shape { public: void Draw() const; void SetRadius(double radius); Circle(); Circle(double x, double y, double radius); protected: double _radius; }; void Circle::Draw() const cout << "[Circle] Position = ( " << _x << ", " << _y << ") " << "Radius = " << _radius << "\n"; }

Shape 클래스와 자식 클래스들(4) 도형객체 생성 및 그리기 int main() { // 도형 객체 생성 및 그리기 Shape s; s.Move(100, 100); s.Draw(); // 사각형 객체 생성 및 그리기 Rectangle r; r.Move( 200, 100); r.Resize( 50, 50); r.Draw(); // 원 객체 생성 및 그리기 Circle c; c.Move( 300, 100); c.SetRadius( 30); c.Draw(); return 0; }

Shape 클래스와 자식 클래스들(5) 도형 클래스들의 상속 계층도 [23-3] 뒤로

보관한 객체를 사용하기 및 문제점 앞의 예에서 shape의 하위클래스인 circle이나 Rectangle클래스를 이용하여 여러 개의 객체를 생성해야 하는 경우, 객체배열을 이용할 수 있다. Circle과 Rectangle을 위한 객체배열을 따로 선언해 주어야 한다. -> 비 효율적 상위클래스의 객체배열로 선언하고 사용할 수 있다. (지난 상속에서, 자식클래스의 포인터는 부모클래스의 포인터로 변환이 가능하다.)

다양한 클래스의 객체를 배열에 담기(1) 도형 클래스의 객체들을 배열에 담아서 사용하는 예 실행 결과 – 항상 Shape::Draw() 가 호출 Shape* shapes[5] = {NULL}; shapes[0] = new Circle( 100, 100, 50); shapes[1] = new Rectangle( 300, 300, 100, 100); shapes[2] = new Rectangle( 200, 100, 50, 150); shapes[3] = new Circle(100, 300, 150); shapes[4] = new Rectangle( 200, 200, 200, 200); for (int i = 0; i < 5; ++i) shapes[i]->Draw(); for (i = 0; i < 5; ++i) { delete shapes[i]; shapes[i] = NULL; }

다양한 클래스의 객체를 배열에 담기(2) 배열과 객체들의 메모리 구조 [23-5]

가상 함수로 문제점 해결하기 Draw() 함수를 가상 함수로 만들면 문제 해결 class Shape { public: void Move(double x, double y); virtual void Draw() const; Shape(); Shape(double x, double y); protected: double _x, _y; }; 객체의 타입에 맞는 Draw()함수가 호출된다. Shape::Draw()함수를 가상함수로 만들면 Circle::Draw()와 Rectangle::Draw()함수 역시 자동적으로 가상함수가 됨 virtual키워드는 클래스의 정의 안쪽에서만 한 번 붙여주면 된다. [23-6]

가상함수 클래스 내에 virtual 키워드로 선언된 함수로, C++ 언어에서는 이를 통해 상속을 이용한 다형성(polymorphism)을 제공 가상 함수의 선언 virtual 함수_선언; 가상 함수는 가상 메커니즘을 구동 시킴 가상 메커니즘 가상 함수로 선언된 함수를 하위 클래스에서 오버라이딩하고, 가상 함수를 호출하면 실제 호출되는 함수는 가상으로 선언된 함수가 아니라, 실제 인스턴스의 타입에 따라 호출 가상 함수는 다형성(polymorphism)을 제공하는 중요한 도구

다형성(Polymorphism)과 가상함수(1) 다른 분야에서의 다형성의 의미 객체지향 프로그래밍에서의 다형성이란 타입에 관계 없이 동일한 방법으로 다룰 수 있는 능력을 말한다. 예) Circle이나 Rectangle 객체들을 각각의 타입에 상관 없이 Shape 객체처럼 다룰 수 있는 능력 [표 23-1]

다형성(Polymorphism)과 가상함수(2) 다형성은 객체간의 결합(Coupling)을 약하게 만들어서, 객체 간의 연결을 유연하게 해준다. // 도형을 원점으로 이동하는 함수 void Controller::MoveToOrigin( Shape* p ) { p->Move( 0, 0 ); p->Draw(); } [23-7]

순수 가상 함수(Pure Virtual Functions) 하위 클래스에서 반드시 오버라이딩해야 할 때 사용 가상 함수의 선언부 끝에 ‘=0’이라는 순수 지시자(Pure Specifier)를 붙인 함수 가상 함수를 선언한 클래스에서는 이 함수를 정의해서는 안 되며, 상속한 클래스에서는 반드시 오버라이딩해야만 한다. 순수 가상 함수를 선언한 기본 클래스에서는 인스턴스를 생성할 수 없다. 순수 가상 함수에 해당하는 멤버 함수는 정의부가 없어 클래스의 인스턴스 생성을 위한 메모리 지도를 만들 수 없기 때문 Shape::Draw() 함수를 순수 가상 함수로 만들어보자. class Shape { public: void Move(double x, double y); virtual void Draw() const = 0; // 중간 생략 /* 함수의 정의를 지워도 컴파일 오류가 발생하지 않는다. void Shape::Draw() const cout << "[Shape] Position = ( " << _x << ", " << _y << ")\n"; } */

순수 가상 함수의 의미 하나 이상의 순수 가상 함수를 포함하고 있는 클래스를 추상 클래스(Abstract Class)라고 부른다. 추상 클래스 타입의 의 객체를 생성하는 것은 불가능하고, 오로지 부모 클래스로서만 사용할 수 있다. Shape::Draw() 함수를 순수 가상 함수로 만드는 것의 효과 Shape 클래스를 추상 클래스로 만들기 때문에 Shape 클래스의 객체를 만들 수 없다. 컴파일러나 다른 개발자들에게 Shape 클래스는 오로지 부모 클래스로만 사용할 것이라는 점을 알리는 역할을 한다. Shape::Draw() 함수를 구현하지 않아도 컴파일 오류가 발생하지 않는다. 컴파일러나 다른 개발자들에게 Shape::Draw() 함수가 자식 클래스에 의해서 오버라이딩 될 것이며, 다형성을 통해서만 호출할 것이라는 점을 알리는 역할을 한다.

다양한 종류의 멤버 함수 상속과 관련해서 지금까지 살펴본 멤버 함수의 종류 일반적인 멤버 함수 가상 함수 순수 가상 함수 어떤 종류의 멤버 함수를 사용할 지에 대한 가이드 라인 처음엔 그냥 멤버 함수로 만든다. 다형성을 이용해야 하는 경우라면 가상 함수로 만든다. 다형성을 위해서 함수의 원형만 필요한 경우라면 순수 가상 함수로 만든다.

오버로딩과 오버라이딩 부모 클래스에서 오버로드된 함수 중에서 어느 것 하나라도 오버라이드 하면 나머지 다른 함수들도 모두 사용할 수 없다. class Pet{ public: void Eat(); void Eat(const string& it); string name; }; class Dog : public Pet { int main() { // 강아지 생성 Dog dog1; dog1.name = "Patrasche"; // 두 가지 Eat() 함수를 호출한다. dog1.Eat(); dog1.Eat( "milk" ); // Error!! return 0; } [23-11]

1. 범용 함수 - 함수 템플릿 2. 범용 클래스 – 클래스 템플릿

함수 템플릿 int, double, ... 형 변수 2개에 대한 swap() 함수 구현하라. #include <iostream> using namespace std; void swap(int &x, int &y); void swap(double &x, double &y); void main(void) { int a = 3, b = 5; double x = 1.1, y = 2.2; cout << "a = " << a << ", " << "b = " << b << endl; cout << "x = " << x << ", " << "y = " << y << endl; swap(a, b); swap(x, y); } void swap(int &x, int &y) { int temp = x; x = y; y = temp; } void swap(double &x, double &y) double temp = x; 함수 템플릿을 사용하면 하나의 함수만으로 모두 수용 가능!  다음 페이지

함수 템플릿 함수 템플릿 : 관련된 함수들의 틀 여러 가지 타입에 대해 공통적으로 적용 가능 사용할 자료형을 매개변수로 전달받음 #include <iostream> using namespace std; template <typename T> void myswap(T &x, T &y); void main(void) { int a = 3, b = 5; double x = 1.1, y = 2.2; cout << "a = " << a << ", " << "b = " << b << endl; cout << "x = " << x << ", " << "y = " << y << endl; myswap(a, b); myswap(x, y); } 아래와 같이 두 줄에 걸쳐 써도 됨 template <typename T> void myswap(T &x, T &y) typename 대신 class 사용 가능 template <typename T> void myswap(T &x, T &y) { T temp = x; x = y; y = temp; } 템플릿 하나로 해결! T  Type의 대표 이름

함수 템플릿 함수 템플릿의 동작 원리 여러 개의 범용 자료형을 갖는 예 컴컴파일 시 함수 템플릿으로부터 해당 타입의 함수가 만들어짐 (Instantiation) swap(T, T)  swap(int, int), swap(double, double)  컴파일 주의 : 함수 템플릿 또는 클래스 템플릿 구현 시 프로토타입을 header 파일로, 구현 부분을 cpp 파일로 분리하여 구현하면 안됨 (Link Error) – 템플릿은 그 자체로 컴파일되는 것이 아님  VC++에서 지원하지 않음?  둘 다 header 파일 또는 둘 다 사용하는 파일 여러 개의 범용 자료형을 갖는 예 #include <iostream> using namespace std; template <typename T1, typename T2> void Print(T1 x, T2 y) { cout << x << "\t" << y << endl; } void main(void) { Print(10, "Hi"); Print(0.23, 15); Print("Hi", 4.54);

함수 템플릿 : 템플릿 함수의 오버로딩 연관된 함수들 : 같은 이름을 가진 하나의 함수 템플릿 사용 컴파일러는 해당 타입에 맞는 함수를 동작하기 위해 오버로딩 처리 함수 템플릿 : 명시적으로 오버로딩 가능 template <typename T> void swap(T &x, T &y); template <typename T> void swap(T &x, T &y, int option); non-template 함수 역시 다른 매개변수로 같은 이름 사용 가능 void swap(int &x, int &y) 함수 호출 순서 1. 이름, 매개 변수가 정확히 일치하는 함수 2. 해당 함수를 만들어 낼 수 있는 함수 템플릿을 사용하여 함수 생성 3. 없다면 에러

클래스 템플릿 문제 int형 값 5개를 배열로 저장하는 클래스를 만들어 보라. (IntArray) double형 값 5개를 배열로 저장하는 클래스를 만들어 보라. (DoubleArray) char형 값 5개를 배열로 저장하는 클래스를 만들어 보라. (CharArray) void main(void) { IntArray IntA; DoubleArray DoubleA; CharArray CharA; int i; for (i = 0; i < 5; i++) IntA.SetX(i, i * i); DoubleA.SetX(i, 3.14 * i * i); CharA.SetX(i, i + 'A'); cout << IntA.GetX(i) << "\t"; cout << endl; for (i = 0; i < 5; i++) cout << DoubleA.GetX(i) << "\t"; cout << endl; cout << CharA.GetX(i) << "\t"; }

클래스 템플릿 문제 - 계속 class IntArray { private : int x[5]; public: void SetX(int index, int value) { x[index] = value; } int GetX(int index) { return x[index]; } }; 문제 - 계속 type을 제외하고는 모두 동일하다 class DoubleArray { private : double x[5]; public: void SetX(int index, double value) { x[index] = value; } double GetX(int index) { return x[index]; } }; 하나의 클래스로 만드는 방법은? 클래스 템플릿 : type의 매개변수화! class CharArray { private : char x[5]; public: void SetX(int index, char value) { x[index] = value; } char GetX(int index) { return x[index]; } };

클래스 템플릿 void main(void) { int형 Array 객체 생성 Array<int> IntA; Array<double> DoubleA; Array<char> CharA; int i; for (i = 0; i < 5; i++) IntA.SetX(i, i * i); DoubleA.SetX(i, 3.14 * i * i); CharA.SetX(i, i + 'A'); cout << IntA.GetX(i) << "\t"; cout << endl; cout << DoubleA.GetX(i) << "\t"; cout << CharA.GetX(i) << "\t"; } int형 Array 객체 생성 #include <iostream> using namespace std; template <typename T> class Array { private : T x[5]; public: void SetX(int index, T value) { x[index] = value; } T GetX(int index) { return x[index]; } }; 추가 : T : type의 매개변수화 필요한 type을 T로 변경 // 멤버함수를 외부에 구현할 때의 구문 template <typename T> T Array<T>(int index) { return x[index]; }

클래스 템플릿 : 예제 - 2개 이상의 type을 매개변수로 받기 #include <iostream> using namespace std; template <typename T1, typename T2> class myclass { private : T1 i; T2 j; public: myclass(T1 a, T2 b) { i = a; j = b; } void show(void) { cout << i << "\t" << j << endl; } }; void main(void) { myclass<int, double> ob1(10, 0.23); myclass<char, char *> ob2('X', "This is a test"); ob1.show(); ob2.show(); }

클래스 템플릿 유용한 클래스들을 템플릿으로 만들어 라이브러리로 준비해 두면 어떨까? C++ 표준 템플릿 라이브러리 (STL) 많이 사용되는 자료구조와 알고리즘을 클래스 템플릿으로 구현 stack, queue, list, set, vector(동적배열), ... search, sort, swap, ...

STL 컨테이너(1) list 클래스를 사용하는 예 #include <list> #include <iostream> int main() { // int 타입을 담을링크드 리스트 생성 std::list<int> intList; // 1 ~ 10까지 링크드 리스트에 넣는다. for (int i = 0; i < 10; ++i) intList.push_back( i); // 5를 찾아서 제거한다. intList.remove( 5); // 링크드 리스트의 내용을 출력한다. std::list<int>::iterator it; for (it = intList.begin(); it != intList.end(); ++it) std::cout << *it << "\n"; return 0; }

STL 컨테이너(2) list 클래스의 탐색 [29-2]

STL 컨테이너(3) 자주 사용하는 STL의 컨테이너 클래스 [표 29-1]

STL 알고리즘(1) sort() 함수를 사용하는 예 #include <algorithm> #include <vector> #include <iostream> int main() { // 동적 배열을 생성해서 임의의 영문자를 추가한다. std::vector<char> vec; vec.push_back( 'e'); vec.push_back( 'b'); vec.push_back( 'a'); vec.push_back( 'd'); vec.push_back( 'c'); std::cout << "\nvector 정렬 전\n"; std::vector<char>::iterator it1; for (it1 = vec.begin(); it1 != vec.end(); ++it1) std::cout << *it1; // sort() 함수를 사용해서 정렬한다. std::sort( vec.begin(), vec.end() ); // 정렬 후 상태를 출력한다. std::cout << "\nvector 정렬 후\n"; std::vector<char>::iterator it2; for (it2 = vec.begin(); it2 != vec.end(); ++it2) std::cout << *it2; std::cout<< std::endl; return 0; }

STL 알고리즘(1) 자주 사용하는 STL의 알고리즘 함수 [표 29-2]