Clone()이란...............
아주 기본적인 어빌리티지만
많은 용도와 쓰임이 있다.
clone()....한마디로,
- 가상 복사 생성자.
생성자는 가상이 될 수 없으나, 복사 생성자를 호출하는 가상 멤버 함수로 가상 복사 생성자를 만들 수 있다.
0;virtual BassClass *clone() = 0;
이런 가상 함수 속에..
virtual BassClass *clone()
...{
return (BaseClass*) new This Class(*this);
}
이러한 오버라이딩을 해주는 것.
즉, 가상 함수를 통한 개체 class의 복사 생성자를 간접 호출하는 것으로
ProtoType Pattern의 Instance를 생성하는 것이다.
Clone()는 호출하는 code에서 정확한 컨텍스트 유형 및 제품 클래스를 모르더라도 적절한 제품?을 생산할 수 있도록 해주는..
실제 클래스 형식을 정확히 몰라도 타입에 구애받지 않고 복사할 수 있는 능력을 가지게 되는
일종의 FACTORY METHOD 인 것이다.
-_-ㅎ
소프트웨어 디자인에서 사전에 정보가 부족한 경우에 ,
사용자 정의 및 확장을 위해 프레임웍으로 소프트웨어 구조를 고안하는 경우
이점을 얻을 수 있다고 한다.
주저리 주저리 떠들지말고... ↓구글 그룹스에서 퍼온 소스 를 보면.......
블라 블라~
Here is where Polymorphic Data comes in.
1
#ifndef _POLYMORF_H
2#define _POLYMORF_H
3
4
5////////////////////////////////////////
6/*
7To be used by polymorf, a Class hasclass has to have
8a member Function called()function called Clone( void ) which news
9a copy of the current object, and returns a pointer
10to the base Class .class. A "virtual" constructor.
11*/
12////////////////////////////////////////
13
14
15template <Class Tclass T> Class Polymorfclass Polymorf
16{
17T* thing; //will be a pointer to the actual object
18
19
20public:
21
22
23Polymorf()
24: thing(0)
25{}
26
27
28Polymorf( const T& value ) //copy constructor
29: thing(0)
30{
31thing = value.Clone();
32}
33
34
35const T& operator=( const T& anObject )
36{
37
38
39if ( &anObject == thing )
40return *thing;
41
42
43if ( thing )
44{
45delete thing;
46thing = 0;
47}
48
49
50thing = anObject.Clone();
51
52
53return *thing;
54
55
56}
57
58
59Polymorf( const T* anObject ) //for convenience only
60: thing(0)
61{
62thing = anObject->Clone();
63}
64
65
66const Polymorf& operator=( const Polymorf& anObject )
67{
68
69
70if ( &anObject == this )
71return *this;
72
73
74if ( thing )
75{
76delete thing;
77thing = 0;
78}
79
80
81if ( anObject.thing )
82thing = anObject.thing->Clone();
83else
84thing = 0;
85
86
87return *this;
88
89
90}
91
92
93Polymorf( const Polymorf& other )
94: thing(0)
95{
96
97
98if ( other.thing )
99thing = other.thing->Clone();
100else
101thing = 0;
102
103
104}
105
106
107operator T&( void ) const
108{
109return *thing;
110}
111
112
113operator const T&( void ) const
114{
115return *thing;
116}
117
118
119T& operator *( void ) const
120{
121return *thing;
122}
123
124
125T& operator ->( void ) const
126{
127return *thing;
128}
129
130
131T* GetThing( void ) const
132{
133return thing;
134}
135
136
137const T& value( void ) const
138{
139return *thing;
140}
141
142
143BOOL good( void ) const
144{
145return ( thing != 0 );
146}
147
148
149virtual ~Polymorf()
150{
151if ( thing )
152delete thing;
153}
154
155
156
157};
158
159
160#endif // _POLYMORF_H
161
162
163////////////////////////////////////////
164//
165////////////////////////////////////////
What this allows you to do is redo the class like this:
1class Person 2
...{ 3
4
5
6
}; 7
8
9
typedef Polymorf<Person> PolyPerson; 10
11
12
class Passenger: public Person 13
...{ 14
15
16
17
}; 18
19
20
class Driver: public Passenger 21
...{ 22
23
24
25
}; 26
27
28
class Child: public Passenger //needs child restraint seat 29
...{ 30
31
32
33
}; 34
A PolyPerson can hold any object that has Person as a base class, even
several generations removed.
PolyPerson Sally(Person());
PolyPerson Joe(Driver());
PolyPerson Sam(Passenger());
Now you have 3 variables, all of the same type, yet with different
qualities if used in polymorphic code.
class Vehicle
...{
PolyPerson Occupant[4];
public:
void AddOccupant( const PolyPerson& person );
const Person& GetOccupant( int which ) const;
};
You can now do this:
Vehicle Car;
Car.AddPerson( PolyPerson(Driver(Jack)) );
Car.AddPerson( PolyPerson(Passenger(Jill)) );
Car.AddPerson( PolyPerson(Child(Britney)) );
Your Car can hold many different types of Persons.
For this to work, the PolyMorfed classes need to have a "Clone()"
function, commonly known as a virtual constructor. It is almost
identical for every case, except for the return type:
BaseClass* Clone( void ) const
...{
return (BaseClass*) new ThisClass(*this);
}
Some older compilers required that virtual functions returned the same
type (BaseClass*) but this is no longer necessary for most compilers.
This makes a copy of the current object and returns a pointer to it.
여기서 Clone()함수는 복사생성자를 호출해서 새로운 객체를 heap에 만들고 그 객체의 주소를 반환한다.
일일이 new해서 만들 것을 clone을 통해서 동적 바인딩 하는 모습을 볼 수 있다.
이때의 강점이라면 캐스팅이라고 할 수 있다.
Polymorf<Person> Sally(Person());
Polymorf<Person> Joe(Driver());
Polymorf<Person> Sam(Passenger());
다들 타입은 같지만 질(?)이 다르다. (It is almost identical for every case, except for the return type.)
왜 다형성 자료형( Polymorphic Data )이라고 부르며
Polymorphic Data에서는 왜 Clone()을 써야 하는지 감이 온다.
다형성 자료와 추상화인터페이스는 많은 일을 가능하게 해주었다. 그 대표적인 예가 잘 들어있는
디자인 패턴을 공부해 보면 if로 분기할 조건들을 오버라이딩을 통해 동적 바인딩 되는 구조를 바탕으로 한다.
하지만 우리는 동적 바인딩(혹은 Run time 함수호출)의 메모리와 속도등의 비효율에 회의를 느끼고
Static(정적) 바인딩으로 방향을 돌리게 된것이다. (아주 극히 드문 경우이다.)
결국 컴파일 타임에 코드를 생성(혹은, 함수 호출이라고나 할까..)하게 하는 이른바, 단위 전략이 나타나게 된 것이다.
난해한 코드들과, 이미 익숙해진 런타임 사고방식속에서 컴파일 타임 테크닉을 사용하는 것은 쉽지 않으나
우리가 지향해야 할 방향임에 틀림없다.
각설은 이정도, 런타임에서의 clone(), 즉 다형성 객체의 역할은
컴파일 타임호출에서 어떤식으로 구현될까..
이것은 단순한 컴파일 타임의 인스턴스화로 해결되지 않는다.
템플릿 인자 갯수가 고정되어 있다는 한계점과,
템플릿 형식으로는 가상함수(virtual)를 표현할 수 없다는 문제를 생각해보자.
결국 템플릿 특수화로도 해결할 수 없던 컴파일 타임의 타입 선택에 대하여 고심하던 차에
이러한 훌륭한 코드가 탄생하는 것이다.
//Typelist 정의부분
template<typename T, typename U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
//Typelist 정의 외의 모든부분. TL은 Loki namespace 내부에 존재한다.
namespace TL
{
....
}
많은 C++ 프로그래머들이 이 다섯줄의 코드를 , "그 무엇보다도 가장 훌륭한 코드이다." 라고 말하곤 한다는데..
ㄷㄷ........
세가지 자료형을 담는 Typelist CharList라면
typedef Typelist<char, Typelist<signed char, unsigned char> >
CharList;
이렇게 사용하면 되는것...... 깔끔하다.
특히 Loki의 typelist.h에서 #define을 통해 나열 방식으로 Typelist를 바꿔주는 매크로가 정의되어 있다고 한다.
위의 CharList라면 이렇게 표현된다.
typedef TYPELIST_3(char, signed char, unsigned char)
CharList;
여기까지는 걍 놀라워 하면 되지만.. 이걸 사용할때는...컴파일 타임속에서 일종의 재귀를 해 주는데, 사용 방법은.. 생략!
Typelist의 탐색, 생성, 수정, 상속관계, Tuple생성등 런타임의 Clone을 뛰어 넘는다.
단지 내공이 부족한 나에게는....
너무나도 어려운 구현이 아닐 수 없다...
(이상, 2008년 고민했던 내용입니다.)
'Programming Language > C++' 카테고리의 다른 글
[D.P] SingleTon (0) | 2011.09.07 |
---|---|
[C Interprinter] Scanner class (0) | 2011.09.07 |
[단위전략] Tipelist - 타입 사이즈 Sort 구현 (0) | 2010.11.04 |