가상이 아닌 함수는 포인터의 정적인 형을 근거로 구동되지만, 가상 함수는 가리키고 있는 객체의 동적인 형을 근거하여 구동된다.
공통된 포인터로 다양한 객체를 가리킬 수 있다.
Musician은 추상적인 클래스
11: virtual void play() = 0; //순수가상함수(첨보는것)
단지 이것만 쓰면 에러
abstract 어쩌고저쩌고… abstract 추상적인 이라는 뜻
추상이란 뭘까…
실제 존재하지 않는것을 유추하는 것이다.
순수가상함수는 상속을 받게 되면 상속클래스내에 함수를 반드시 만들어 줘야 한다.
가상함수는 상속을 받더라도 만들지 않아도 된다.
순수가상함수가 있으면 추상클래스라 한다.
1: //순수가상함수, 오버라이딩
2: #include <iostream.h>3:4: class Musician //제일 상위클래스(object)5: {6: public :
7: virtual void Greet() = 0; //제일 상위클래스 안에 함수앞 virtual8: // {
9: // cout << "안녕하세요. 저는 뮤지션입니다." << endl;
10: // }
11: virtual void play() = 0; //순수가상함수(첨보는것)12: // virtual void play() //함수인터페이스만 있음
13: // {
14: // }
15: };16:17: class Singer : public Musician //상속18: {19: public :
20: void Greet()
21: {22: cout << "안녕하세요. 저는 가수입니다." << endl;
23: }24: void play()
25: {26: cout << "노래하는 중입니다." << endl;
27: }28:29: };30:31: class Drum : public Musician32: {33: public :
34: void Greet()
35: {36: cout << "안녕하세요. 저는 드럼입니다." << endl;
37: }38: void play()
39: {40: cout << "드럼 치는 중입니다." << endl;
41: }42:43: };44:45: class Bell : public Musician46: {47: public :
48: void Greet()
49: {50: cout << "안녕하세요. 저는 벨입니다." << endl;
51: }52: void play()
53: {54: cout << "벨 치는 중입니다." << endl;
55: }56: };57:58: class Guitar : public Musician59: {60: public :
61: void Greet()
62: {63: cout << "안녕하세요. 저는 기타입니다." << endl;
64: }65: void play()
66: {67: cout << "기타 치는 중입니다." << endl;
68: }69: };70:71: int main()
72: {73: // Musician M;
74: Singer S;75: Drum D;76: Bell B;77: Guitar G;78: Musician *p[4] = {&S, &D, &B, &G};79: //동적기반호출 (객체를기반으로), for문 이용 간단하게 호출
80: for(int iCnt=0; iCnt<4; ++iCnt)81: {82: (*p[iCnt]).Greet(); //우선순위 높은 () 필수, p[iCnt]->Greet();
83: }84: for(int iCnt=0; iCnt<4; ++iCnt)85: {86: (*p[iCnt]).play(); //우선순위 높은 () 필수, p[iCnt]->Greet();
87: }88:89: //정적기반호출, 코드마다 호출해줘야하는 단점
90: /* M.Greet();
91: S.Greet();92: D.Greet();93: B.Greet();94: */95: return 0;
96: }97:98:
c++ 창시자는 누구 –> bjarne stroustrup
자바는 다중 상속이 없는 대신 인터페이스 클래스가 있다.
1: //생성자, 복사생성자, 대입연산자, 소멸자는 왜 필요한가(추가로 프린트함수)
2: //동적할당할 때 문제가 생기기 때문이다
3: //virtual은 소멸자와 print에만 왜 쓰는지?
4: //
5: #include <iostream.h>6:7: class Music
8: {9: public :
10: int *p;
11: Music()12: {13: cout << "Music 디폴트 생성자 호출" << endl;
14: p = new int;15: *p = 100;16: }17: virtual ~Music() //소멸자 앞 가상 붙이면 다시 되돌아온다18: {19: cout << "Music 소멸자 호출" << endl;
20: delete p;
21: }22: virtual void print(ostream * o) //반드시 virtual23: {24: *o << *p << endl;25: }26: };27:28: class Rock : public Music29: {30: public :
31: int *p2;
32: Rock()33: {34: cout << "Rock 디폴트 생성자 호출" << endl;
35: p2 = new int;36: *p2 = 200;37: }38: ~Rock()39: {40: cout << "Rock 소멸자 호출" << endl;
41: delete p2;
42: }43: void print(ostream * o)
44: {45: *o << "p가 가르키는 곳의 값 " << *p << endl;
46: *o << "p2가 가르키는 곳의 값 " << *p2 << endl;
47: }48: };49:50: ostream & operator<<(ostream & o, Music & r) //외부에선언 내부에서 쓰는게 아니니깐51: {52: r.print(&o); //r.print(&cout);
53: return o;
54: }55:56: ostream & operator<<(ostream & o, Rock & r)
57: {58: r.print(&o);59: return o;
60: }61:62: int main()
63: {64: // Rock obj;
65: Music *p = new Rock;
66: (*p).print(&cout); //p -> print(&cout);
67: delete p; //Rock 소멸자 x68: return 0;
69: }70:
#include <iostream.h>
//클래스 함수포인터
class a
{
public:
void test()
{
cout << "hi" << endl;
}
};
int main()
{
a obj;
obj.test();
void(a::*fp)()=obj.test;
(obj.*fp)(); //외우자
return 0;
}
'C 언어 > C++' 카테고리의 다른 글
c++ 기초단계 (11/21) (0) | 2011.11.21 |
---|---|
c++ 기초단계 (11/18) (0) | 2011.11.18 |
c++ 기초단계 (11/16) (0) | 2011.11.16 |
c++ 기초단계 (11/15) (0) | 2011.11.15 |
c++ 기초단계 (11/14) (0) | 2011.11.14 |