실행시에 객체의 클래스 이름얻기
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#include "stdafx.h" #define DEBUG class CObject { public: virtual char* GetClassName() const{ return NULL;} }; class CMyClass : public CObject { public: static char lpszClassName[]; virtual char* GetClassName() const { return lpszClassName; } }; char CMyClass::lpszClassName[]="CMyClass1"; void main() { CObject *p; p=new CMyClass; printf("%s",p->GetClassName()); #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } 메크로 사용 #include "stdafx.h" #define DEBUG #define DECLARE_CLASSNAME(s) static char lpszClassName[] #define IMPLEMENT_CLASSNAME(s) char s##::lpszClassName[]=(#s) class CObject { public: virtual char* GetClassName() const{ return NULL;} }; class CMyClass : public CObject { public: //static char lpszClassName[]; DECLARE_CLASSNAME(CMyClass); virtual char* GetClassName() const { return lpszClassName; } }; //char CMyClass::lpszClassName[]="CMyClass1"; IMPLEMENT_CLASSNAME(CMyClass); void main() { CObject *p; p=new CMyClass; printf("%s",p->GetClassName()); #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } |
소멸자에서 가상함수 호출
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include "stdafx.h" #include <stdio.h> #define DEBUG class CBase{ public: CBase(){ DoVirtual();//가상함수를 호출 X } ~CBase(){ DoVirtual();//가상함수를 호출 O } void DoIt() { DoVirtual();//가상함수를 호출 O } virtual void DoVirtual() { printf("CBase\n"); } }; class CDerive : public CBase { public: virtual void DoVirtual() { printf("CDerive\n"); } }; void main() { CDerive b; b.DoIt(); #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } |
가상 소멸자
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include "stdafx.h" #include <stdio.h> #include <string.h> #define DEBUG class A{ char* a; public: A(char* s){ a=new char[strlen(s)+1]; strcpy(a,s); } virtual ~A(){ delete[] a; printf("Destructor of class A\n"); } virtual void Print() { printf("%s\n",a); } }; class B : public A{ char* b; public: B(char* s,char* t):A(t){ b=new char[strlen(s)+1]; strcpy(b,s); } virtual ~B(){ delete[]b; printf("Destructor of class B\n"); } virtual void Print(){ A::Print(); printf("%s\n",b); } }; void main() { A* pA; pA=new B("hello","world"); pA->Print(); delete pA; #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } |
상위 클래스로 사용될 것 같은 클래스의 생성자에서 동적으로 메모리를 할당하는 경우, 소멸자를 가상으로 선언하라.
가상함수를 이용한 객체지향 모델
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include "stdafx.h" #define DEBUG class CBase { public: void Print() { printf("pre virtual\n"); OverrideMe(); printf("post virtual\n"); } virtual void OverrideMe() { printf("CBase\n"); } }; class CDerive : public CBase { public: void Draw() { printf("draw\n"); } virtual void OverrideMe() { CBase::OverrideMe();//가상함수의 일반적인 설계규칙은 //베이스 클래스의 가상함수에 기능을 확장하는 것이다. printf("CDerrive\n"); } }; void main() { CDerive d; d.Print(); #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } |
pre virtual CBase CDerrive post virtual
가상함수
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include "stdafx.h" #define DEBUG class A{ int i; public: A(){ i=0; } virtual void Print() { printf("%d\n",i);} }; class B : public A { int i; public: B(){ i=1; } virtual void Print() { printf("%d\n",i);} }; class C : public B { int i; public: C(){ i=2; } virtual void Print() { printf("%d\n",i);} }; void main() { A* ap; B b; C c; ap=&b; ap->Print(); ap=&c; ap->Print(); #ifdef DEBUG //cmd char e; scanf("%c",&e); #endif } |
베이스 클래스이 포인터를 이용하여 하위 클래스의 멤버 함수를 호출하기 위해서는 멤버 함수가 가상이어야 한다. 즉, 하위 클래스에서 오버라이딩할 것 같은 함수는 베이스에서 모두 가상으로 선언한다.
복사생성자 operator
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include "stdafx.h" #include <string.h> #include <conio.h> #define DEBUG class CStr{ char* str; public: CStr(char *s=""){ str = new char[strlen(s)+1]; strcpy(str,s); printf("construction\n"); } CStr(const CStr &s){ str = new char[strlen(s.Get())+1]; strcpy(str,s.Get());//const 객체는 const 멤버 함수만을 호출할 수 있다. printf("construction\n"); } ~CStr() { delete[] str; printf("destructor\n"); } char* Get() const{ return str; } void Print() {printf("%s\n", str);} CStr& operator=(CStr &s){ delete[] str; str=new char[strlen(s.Get())+1]; strcpy(str,s.Get()); printf("=operator\r\n"); return *this; } }; void f(CStr s){ s.Print(); } void main() { CStr s("hello"),t("world"); CStr u=s;//3. 객체의 선언에 사용된 대입 연산자 f(u);//1. 함수의 파라미터로 객체를 전달 s=t;//*객체간의 대입문은 복사 생성자를 호출하지 않는다. //operator= 호출 s.Print(); #ifdef DEBUG //cmd char c; scanf("%c",&c); #endif } |
operator의 필요성
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include "stdafx.h" #include <string.h> #include <conio.h> #define DEBUG class CStr{ char* str; public: CStr(char *s=""){ str = new char[strlen(s)+1]; strcpy(str,s); printf("construction\n"); } CStr(const CStr &s){ str = new char[strlen(s.Get())+1]; strcpy(str,s.Get());//const 객체는 const 멤버 함수만을 호출할 수 있다. printf("construction\n"); } ~CStr() { delete[] str; printf("destructor\n"); } char* Get() const{ return str; } void Print() {printf("%s\n", str);} }; void f(CStr s){ s.Print(); } void main() { CStr s("hello"),t("world"); CStr u=s;//3. 객체의 선언에 사용된 대입 연산자 f(u);//1. 함수의 파라미터로 객체를 전달 s=t;//*객체간의 대입문은 복사 생성자를 호출하지 않는다. //그래로 복사(bitwise copy)//error s.Print(); #ifdef DEBUG //cmd char c; scanf("%c",&c); #endif } 삭제 |
복사생성자
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include "stdafx.h" #include <string.h> #include <conio.h> #define DEBUG class CStr{ char* str; public: CStr(char *s=""){ str = new char[strlen(s)+1]; strcpy(str,s); printf("construction\n"); } CStr(const CStr &s){ str = new char[strlen(s.Get())+1]; strcpy(str,s.Get());//const 객체는 const 멤버 함수만을 호출할 수 있다. printf("construction\n"); } ~CStr() { delete[] str; printf("destructor\n"); } char* Get() const{ return str; } void Print() {printf("%s\n", str);} }; void f(CStr s){ s.Print(); } void main() { CStr s("hello"); f(s); #ifdef DEBUG //cmd char c; scanf("%c",&c); #endif } |
복사 생성자가 호출되는 경우 1. 함수의 파라미터로 객체를 전달 2. 함수가 객체를 리턴 3. 객체의 선언에 사용된 대입 연산자 4. 임시 객체의 복사
복사생성자의 필요성 샘플
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include "stdafx.h" #include <string.h> #include <conio.h> #define DEBUG class CStr{ char* str; public: CStr(char *s=""){ str = new char[strlen(s)+1]; strcpy(str,s); printf("construction\n"); } ~CStr() { delete[] str; printf("destructor\n"); } void Print(){ printf("%s\n",str); } }; //void f(CStr s)오류 //생성자에서 동적으로 메모리를 할당하는 //객체를 파라메터로 전달할 때는 항상 포인터 혹은 레퍼런스를 전달한다. void f(CStr& s) { s.Print(); } void main() { CStr s("hello"); f(s); #ifdef DEBUG //cmd char c; scanf("%c",&c); #endif } |