This page is in Pre Alpha. That means no grammer checks, no editting and speeling mistakes galore! The explanations and the final version will come soon. Check it out at your own risk! The key to the future, according to Microsoft is COM or the Component Object Model. Today, COM forms the core of all Microsoft technologies, and provides the skeleton for all it's future strategies. OLE (pronounced Olay) sits on top of COM and ActiveX sits on top of OLE. To most people ActiveX is nothing but a series of OLE classes. If COM is so important then the entire world must learn it, or so you may say. But this is easier said than done. COM is extremely difficult to understand (if you attempt to learn it using the documentation provided by Microsoft) The gist of COM, if stated in English could be put in the following words. If you consider a Microsoft product like Visual Basic, you will find the concept of components. These components may have properties and events and other attributes. These components can be inserted into any container like VB, PowerBuilder etc. and we can integrate the component into our applications. Coding a COM object was never a bother as long as we used Visual Basic. But the irony of the situation is that if we wanted to do the same thing from C++, then we will have a problem. It was extremely difficult to use ActiveX from C++, even though the entire ActiveX, OLE, COM families are based on C++. This was till the time Microsoft introduced Visual C++ 5.0 Microsoft knew that they could not change C++ as a language, because they did not own it. They have added extensions to the language using their product Visual C++. They have added some ingredients which allows them to stake a claim saying that C++ understands COM, or more specifically Visual C++ 5.0, the compiler understands COM. In this tutorial we will attempt to analyze Microsoft's claim and try to rip apart their claims. But before we do that we will educate ourselves about some of the lesser know aspects of C++. If we are put in an un-envious position where we are told to write code which will be used to sort an array of ten numbers. This is a simple task, usually the first lessons undertaken in any C/C++ class. If the instructor decides to add spice and asks us to print out these numbers, then this is no arduous task. This is because we are aware that the first member of the array is stored at a[0], the next member at a[1] and so on. Hence printing can be effected by using a[0], a[1] etc. This task does not involve heavy overheads because we are aware of the fact that internally an array of chars, int's, or longs will be made up of one, two or four memory locations respectively. This is a specific instance of an array of 'known' datatypes. What would happen if the array contains instances of 'zzz', an arbitrary object. Our sorting program will simply fail to take off. The need of the hour is to be able to functions that will carry out the task of sorting irrespective of the datatypes involved. Programs should have the ability to tackle any datatypes, be it of known nature like ints, chars or any other in-house datatypes like 'zzz'. In other words we would like to produce code that is generic. Fortunately, C++ provides us with a tool that allows us to do just that. We will first look at this aspect of C++ before answering the 'Question of the day' i.e. does VC++ 5.0 support COM. To understand more about creation of generic code, we will look at some simple examples. Program 1 : #include class zzz { public: int i; zzz() { printf("in zzz...%d\n",sizeof(i)); } }; main() { zzz a; } You will realize that when we say 'int i', i is not a variable but an an object which is an instance of a class int. There is no difference between class int and zzz, the compiler does not differentiate between the two. So wherever you can give a class, you can give an int, or you could give 'zzz', they are all the same. The problem is that by saying that i is an int, we are laying down a single rule that henceforth because i is an int , it cannot be anything else. However 'C' realizes this, not at the time when the code is being typed in, but at time of compiling the code. When the compiler encounters the 'i', he has to be aware of the class-type of 'i', without such a knowledge of this the compiler cannot allocate memory nor can it invoke the constructor. Delaying this information, from being supplied at coding time to the time when compilation starts, would mean availing the flexibility of having code which can work with any datatypes. This is the basic tenet of the Template Classes. They allow us to defer the declaration of the datatype to the time where the compilation starts. Create the following program as 'Console Application' using MS-DEV. Using 'Console Application' allows us to use the keyword 'main' Program 2 : #include template class zzz { public: T i; zzz() { printf("in zzz...%d\n",sizeof(i)); } }; main() { zzz a; zzz b; } In the above program instead of stating that 'i' is an object that looks like 'int', we say that it now resembles 'T'. So when we are writing the code, we am not making any assumption regarding the datatype of 'i'. The datatype could be a 'zzz', it could be a 'yyy', it could be anything under the sun( or for that matter anything above the sun can be included too). If we can do this, then when we say Alt-B B, C++ should know whether 'i' is an int or a char or a long. Depending on the data that we choose to supply, C++ will decide the data type of 'i'. That means when we get the obj file, there will be no T. Had we said 'int i', then this goes to the obj file and a certain amount of memory is allocated for i. Instead we have chose to use 'T' which allows us to use any datatype . Though this assumes the dimension of using a glorified and extremely powerful macro, this is not true because in a macro you don't have such a degree of flexibility. Comparisons between a macro and the using the Template Classes are uncalled for. Because when we use the template classes, just before the compilation takes place, somebody comes in and replaces all T's with the datatype that we have given. This is not possible in case of the macro. Using the template classes is more than using the services of the preprocess. In the above program instead of saying class 'zzz', we have used a template and then we write class zzz. Whenever you say 'zzz a', the constructor gets called, and constructor can get called with parameters. You will get an error message because now instead of saying 'zzz a', you will have to say 'zzz a'.When C++ reads this line. The 'T' in the class definition become an 'int'. So wherever he sees T, it will replace it with int. That means there is an extra stage in the compilation process now. At this juncture if you choose to write 'zzz b', C++ will create another class internally. Hence internally there will be no T, there will be an int and a char. In that sense this has lead to the creation of two different classes. For understanding purposes you can call it as zzz1 and zzz2. The resident wag among us tells us that this is akin to using a typedef. However a typedef is like a '#define'. So you cannot equate the two concepts, because a typedef is very static. A typedef is used for conveying the message that wherever the compiler encounters a 'T' it should be replaced by an int. However in the programs given above we are replacing one instance of 'T' with an int whereas the other 'T' is replaced by a 'char'. We challenge anyone to do the same using typedef's and without involving any further overheads. To silence our critics we will go a step further. Program 3 : #include template class zzz { public: T i; U k; zzz() { printf("in zzz...%d\n",sizeof(i)); printf("in zzz...%d\n",sizeof(k)); } }; main() { zzz a; } In zzz we have used two parameters. Though this increases the complexity of the program. It serves as a good learning experience for may of us. Unlike in the preceding program where we have used 'known' datatypes, in the following program we have used a class as the parameter to the template class. Such a move, we believe will be sufficient to silence our detractors. Program 4 : #include template class zzz { public: T print( T i) { return i; } }; main() { zzz k; printf("%d\n",k.print(100)); } In the above program when we chose to have int as a parameter to 'zzz' nothing stops us from saying printf("%d\n",k.print(100)); In this case T becomes int, so the return value will also be an int. For those who are all at sea, we will first attempt to understand the mechanics involved. This should be enable us to obtain a cleared picture of the whole affair. Writing code become increasingly complicated because at the time of writing the code, we are not aware of the datatype of 'i', assuming it's datatype is fraught with dangers as we can assume that 'i' could be anything. This makes the whole program dynamic. Return values can also be dynamic in nature. Programs involving pointer can assume dynamic nature because of a simple reason. As 'char' and not 'char *' is a datatype similarly 'T' is a datatype which is available at compile time, hence T *i becomes a pointer to 'T' which can point to any datatype. Before we bit adieu to the Template Classes, we provide the last example of the series. Program 5 : #include template class zzz { public: zzz() { char a[j]; printf("j=%d\n",j); a[0]='s'; } }; main() { zzz a; } When we say 'zzz a', 6 becomes the value of j. Since we have said class T, the class signifies that we are deciding the data type of T, instead if we had chosen to use a variable, then we are saying that when C++ create something called zzz, we are going to give that variable a value. This could not be done in C++ if had not used templates. So the whole idea of templates is that you can decide the data types of variables when we want to plus we can introduce variables which will have certain values. So the whole idea is that we can write code which is abstract and more generic. The overloaded programmer and function : People have very volatile memories. They would have probably forgotten all about operator overloading and the related concepts. So to refresh their memories we have presented a small example which will act as a revision for them. Program 6 : #include class zzz { public : int i,j; zzz(int x = 0, int y=0) { i=x;j=y; } void print() { printf("%d..%d\n",i,j); } void operator = (zzz d) { printf("%d..%d..%d..%d\n",i,j,d.i,d.j); i=d.i; j=d.j; } }; main() { zzz a(1,2); zzz b(10,11); a=b; a.print(); } In the above program all that we have to understand is that if we write 'a=b', for some reason we don't get an error, a will now have it's i and j equal to that of b. This is no black magic. It so happens that when we wrote 'a=b', we actually wrote a.=(b); It simply means that the operator should be understood as a function, so when we say operator = it is a function which takes a 'zzz' and the return value is a void. Please take into account the fact that when we write i and j, we are not writing i and j, but we are writing 'this->i' and 'this->j'. So now here if we choose to display the values, the 'd.i' and the 'd.j' will be that of b which is 10 and 11, whereas 'i' and 'j' will be that of a. If we say that i = d.i and j=d.j this will work right in the above program but not in the next program. Program 7 : #include class zzz { public : int i,j; zzz(int x = 0, int y=0) { i=x;j=y; } void print() { printf("%d..%d\n",i,j); } zzz operator = (zzz d) { printf("%d..%d..%d..%d\n",i,j,d.i,d.j); i=d.i; j=d.j; //return *this; return d; } }; main() { zzz a(1,2); zzz b(10,11) zzz c(100,101); c=a=b; a.print(); c.print(); } The multiple occurrences of '=' will not work So we have no choice but to say that the return value is zzz and then we can return either d or alternately we can say *this, where 'this' is a pointer. Since we can be in an extremely kinky mood and would like to say here a->i and a->j The question is can we pull it off? We can say 'this' because a happens to be an object, not a pointer. Had it been a pointer then we would have had no problems at all. For the ones with the volatile memory, let us remind them that the = is an operator so let's stop here and have a good look at the outcome. Program 8 : #include class zzz { public : int i,j; zzz(int x = 0, int y=0) { i=x;j=y; } void print() { printf("%d..%d\n",i,j); } void operator -> () { printf("%d..%d\n",i,j); } }; main() { zzz a(1,2); a->i=1000; } When we are saying a->, we are overloading the ->. When we say that we are overloading the ->, a-> has to stand for something. For the kinkier minds let's present a question. Can a-> stand for void? The answer is a obvious no - We get an error. Program 9 : #include class zzz { public : int i,j; zzz(int x = 0, int y=0) { i=x;j=y; } void print() { printf("%d..%d\n",i,j); } zzz * operator -> () { printf("%d..%d\n",i,j); return this; } }; main() { zzz a(1,2); a->i=1000; a.print(); } When we say a->, all that we are saying is that -> is an operator. But it is an unary operator. So we have actually written this as 'a.->', no parameter needed. Because it is a unary operator like the ++. Unary operator do not take any parameters . So because it is an unary operator, the -> function gets called and we are saying that it returns 'this'. What is this, it a pointer to 'zzz'. So this like saying a.i = 1000. We just wanted to show you that the -> is an operator . It can be overloaded. If you are questioning your wisdom of painstakingly going through the entire tutorial without a mention of VC++ 5.0, you are probably wondering as to where you can use all this knowledge. We will answer that question after you have checked out our next program. Program 10 : #include class aaa { public: int i; void print() { printf("%d..aaa\n",i); } }; class bbb { public: int j; void print() { printf("%d..bbb\n",j); } }; class ccc { public: int k; void print() { printf("%d..ccc\n",k); } }; template class zzz { public : T p; T * operator ->() { return &p; } }; main() { zzz a; a->j=100; a.p.print(); zzz b; b->i=10; b.p.print(); } The three classes (aaa, bbb, ccc) are useless classes. The real work gets done in class 'zzz'. If we have to create an object that looks like zzz, we will have to say zzz<****> a; Depending upon what we write within the angle brackets, the value of b changes. we are allowed to say a.p.print. So if we change aaa to bbb or ccc, print gets called. If we say a->j. it will spew out an error message for aaa and ccc. When we say operator -> and return &T it implies that aaa, bbb, ccc are collection of functions, variables. An OCX is a similar concept, it is nothing but a collection of properties, methods, events. Properties, methods, events are nothing but variables and functions. So if we now create an object 'a' that looks like zzz and we give it bbb as the parameter, then we have the capability of referencing all the members of bbb. If instead we choose to replace 'bbb' with 'ccc' then we can access all the members of 'ccc'. This lays before us an unprecedented amount of flexibility. The three classes mentioned above can have their unique identification code, which may be tentatively be called as it's UUID. We could also have some code in zzz like 'CreateInstance' which will have the ability to call (invoke) any class that we might choose to use. That means from 'a' we can call all the functions that we desire. So if there are twenty functions then we can call any or all these twenty. That is the first advantage. But the second advantage is that that our code remains the same. Which implies that we will always say zzz a , and by using a->, we can access all functions that we ever dreamt of. That is what we mean by smart pointers.