.Open Pointers to C++ documentation and help C++ Class Libraries and "STL" is the "Standard Templates Library". (Mumit's Historical STL Guide for Newbies): .See http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html (Musser's STL Book): .See http://www.cs.rpi.edu/~musser/stl-book/ . Local (C++ FAQ): local .See http://www.csci.csusb.edu/dick/doc/C++.FAQ (from usenet), .See http://www.csci.csusb.edu/dick/samples/c++.FAQ.html (from my students). (C++ Libraries FAQ): local .See ./c++.libraries.html .See http://www.csci.csusb.edu/dick/doc/C++.libraries.FAQ (cctype): local sample .See ./c++.libraries.html#cctype (string): the C++ string library... $TBA Is one string inside another? .See http://www/dick/examples/stringFind.cpp (Course Materials for CS201 from way back): local .See http://www.csci.csusb.edu/dick/cs201/ (C++ functions): local .See http://www.csci.csusb.edu/dick/cs202/functions.html (C++ inheritance): local .See http://www.csci.csusb.edu/dick/cs202/inheritance.html (C++ iomanip Inpu/output Manipulators): local .See http://www.csci.csusb.edu/dick/cs202/iomanip.html (C++ Linked data structures): local .See http://www.csci.csusb.edu/dick/cs202/linked.html (C++ UNIX make): local .See http://www.csci.csusb.edu/dick/cs202/make.html (C++ pointers): local .See http://www.csci.csusb.edu/dick/cs202/pointers.html (C++ STL): local .See http://www.csci.csusb.edu/dick/samples/stl.html .See http://www.csci.csusb.edu/dick/samples/stl.algorithms.html .See http://www.csci.csusb.edu/dick/cs202/stl.html and off site .See http://www.sgi.com/tech/stl/ (C++ templates): local .See http://www.csci.csusb.edu/dick/cs202/templates.html (C++ typedef): local .See http://www.csci.csusb.edu/dick/cs202/typedef.html (C++ vectors): local .See http://www.csci.csusb.edu/dick/cs202/vectors.html (C++ Examples of Code): local .See http://www/dick/examples/ .See http://www/dick/cs320/c++/ . Off campus (Reference on C++ and STL): ref .See http://www.cppreference.com/index.html (C++ source code): .See http://www.Planet-Source-Code.com/PlanetSourceCode/ (Irritating: cookies, advertising, menus, ...) (C++ Glossary): local .See http://www/dick/samples/c++.glossary.html and .See http://www/dick/samples/objects.glossary.html . Frequently Asked Questions (C++ FAQ): local .See http://www/dick/doc/c++.FAQ . Syntax (C++ Lexemes): local .See http://www/dick/samples/c++.glossary.html#Lexemes C++ has always had a BNF-like description of its syntax since it was C. However the precision of this description has varied as has the language being described. Syntax summary from the draft standard December 1996: (C++ draft syntax): .See http://www/dick/c++std/cd2/gram.html Latest MATHS version (based on December 1996 draft) .See http://www/dick/c++std/syntax.html ARM version Circa 1990(C++ as updating C and giving the same value) .See http://www/dick/samples/c++.syntax.html . Semantics There is no standard and formal semantics for C++. Learning what C++ means, depends on interpreting the English in the documentation. A number of researchers are taking steps in the direction of giving rigorous descriptions of the meaning of parts of C++. The Basic Type System .See http://www.cs.iastate.edu/~leavens/larchc++.html I have some notes towards a formal semantics of C .See http://www/dick/samples/c.semantics.html that may form a basis for further work on C++. . C++ Standard Library or STL .See http://www.sgi.com/tech/stl/ . Standards I have summarized the online information on the American and international standardization process in .See http://www/dick/c++std/ They released an HTML version of the latest draft ANSIISO standard for comment in December 1996 and I have a copy at: .See http://www/dick/c++std/cd2/ The ISO process was completed in November 1997, but this standard will probably never have a legal online copy! ISO and ANSI needs the money made by selling paper copies of the standard. . The Standard Template Library This could be the biggest advance over C in the whole package! Think: real arrays, matrices, stacks, queues, trees, hash tables, sets and so on -- ready-to-use! STL::=Standard Template Library, a collection of predefined data structures and classes and functions that can handle any class of object. We have some local notes on this .See http://www/dick/samples/stl.html Also see Mumit's historical STL Newbie Guide: .See http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html (C Library Reference Guide): webmonkeys??? .See http://www.acm.uiuc.edu/webmonkeys/book/c_guide/index.html .Open Inheritance and Polymorphism .Open Inheritance . Why Inheritance It is very irritating to notice that you are about to write two almost identical classes - perhaps they only differ in one function. Perhaps that function is called in exactly the same way but does something slightly different to objects of the different classes. It is even more irritating to realize that a new class you want to create is almost the same as an existing class. There new class has an extra function and one changed definition perhaps. This happens often enough in real software for people to have invented a set of techniques for handling it. These come under the heading of "inheritance" and "polymorphism". Here are pointers to definitions: inheritance::=http://www/dick/samples/glossary.html#inheritance. Polymorphism::=http://www/dick/samples/glossary.html#polymorphism. . Practical Example Inheritance lets you use and enhance an existing class without changing that class. . Programming by Extension Suppose you are programming for a college. They have already have designed, written, coded and tested a class called `Person`. An object in this class holds personal information about somebody like their Social Security Number, their names, their address, their gender, date_of_birth(dob), phone number, and so on. A Person also has functions (`know-how`) that can print the information in a standard format, display it, construct a new person from given data, destroy the records of a person, increase the age, change the name, handle a change of address, ... and so on. Further the college also wants a Faculty class, a Student_assistant class, and a Staff class that are all different kinds of People! A student is a special kind of Person - one that can take courses, can add and drop sections, has a GPA, and so on. Just like a Person a student need to be able to print itself, display itself, construct it self, destroy all its data, increase its age, change a name, change an address, ... plus doing student things like adding, dropping, passing, failing, and such. In the old days you had to copy the Person class file and edit it to make the Student class. But this will take time and may introduce errors. Further, if something changes in the Person class (like change the year in the date of birth from 2 digits to 4 digits say) or adding a new function, forces you to duplicate the changes in the Student class. It would be better to define the class Student so that it explicitly had a field for the personal data and #include the file containing the Person classes code (`person.h`), like this: .As_is #include "person.h" .As_is class Student { .As_is private: .As_is Person person; .As_is float GPA; .As_is //data structures pointing to sections ... .As_is public: .As_is //add, drop, pass, fail, .... .As_is //copy public functions from Person .As_is };//class Student The code for the functions in student mimicking a Person will be like this: .As_is void Student::display(){ person.display(); ...} .As_is void Student::inc_age(int years){person.inc_age(years);...} and so on. Similarly for the other "People-like" classes: Faculty, Staff, etc. If Person is changed by adding or deleting any functions then so must all these other classes. This is not a good use of our time. The better solution is called "inheritance". It makes sure that a Student has a complete up-to-date Person as part of the student, but also, automagically gives the functions of Person to a Student. The code is simple we just add .As_is : public Person to the class header of Student: .As_is #include "person.h" .As_is class Student : public Person { .As_is public: .As_is //add, drop, pass, fail, .... .As_is private: .As_is float GPA; .As_is //data structures pointing to sections .As_is };//class Student The above means that Student is `derived` from Person. Student `inherits` properties of a Person. Person is said to be the `base` of a Student. There is no need to declare or define functions that can be done by a Person. All Students `inherit` them from their `parent`: `Person`. Similarly we can `derive` Faculty from Person. We could also derive Staff from Person. We could perhaps derive Student_Assistant from Student or from Person. Now when Person changes it as if all the other classes are updated to fit. Inheritance is a labor-saving device. . How It Works in C++ C++ inheritance is based on a pair of techniques chosen to make inheritance an efficient process. The compiler does most of the work. The running program (normally) does not have to decide what function or data item is to be used in each case. The choice is made by the compiler and encode into the executable program. The compiler finds the right function to apply by looking at the type of object: Person or Student or Faculty etc. If a function only appears in Person but is applied to a Student then the parents function is called. If a function is only in the Student then the compiler uses this function. If a function is declared in but Student and Person then the compiler chooses the Student's version. This is called over-riding. Note: There is a way to ask for a slower and more dynamic implementation that is discussed later in the notes. In some object-oriented languages the functions and data have to be searched for inside the hierarchy of classes making op a particular object. The data describing a Person is actually hidden inside the Student. In C++ the base component is placed in memory before the items added by Student. .As_is <------------Student--------> .As_is <---Person----><-added data-> However these data items are not explicitly mentioned `inside` Student. There is no need to declare a `Person person` in Student... but the data is hidden in there just the same. This means the address of the start of a student is automatically also the address of the start of a Person (Person's data is before the added data). So all the machine code that accesses `person.name` for a person could in theory also access `student.name` - except that no object except a `bona fide` Person can access a Person's data normally. The compiler also makes sure that Peoples data can not be corrupted by deriving a new class from it. A student does not get any privileged access to its Person's data! . Words We say that Student is `derived` from Person. We say that Person is the `base class` of a Student. We can also say that Student is a `child` of Person and Person is the (or a) `parent` of Student). We can also talk about Student being the class and Parent its `super-class`, or the Parent having a `subclass` Student. We can also say that Student `extends` Parent. We have all these different words because object-oriented languages are recent developments and their inventors all chose their own words for their ideas. In the Unified Modelling Language we talk about a derived class being a `specialization` of the parent, and the parent or base being a `generalization` of the child/derived class: .Table .Row child derived subclass specialized .Row parent base superclass generalized .Row method function method operation .Close.Table For more on the the different words used by different groups of people see .See http://www/dick/samples/objects.glossary.html and for some informal definitions see .See http://www/dick/samples/objects.glossary.html#Informal Definitions of Terms . Inheriting Operations and Data In the above Student and Faculty had no special access to the data they inherited from their base class: Person. We can easily change Person so that it shares its private data with classes derived from it and no others. It just a matter of using the word: "protected" in place of the word "private": .As_is class Parent{ .As_is public: //things any class can access .As_is private: //things only Parent can access. .As_is protected: //things that Parent and Children can access .As_is };//end Parent .As_is class Child: public Parent{...} Protected data and functions are declared exactly like private and public data and functions. The word "protected" and symbolic colon(":") are placed before a list of declarations in the class that the derived class shares with its children. . Diagrams Diagrams can make inheritance much clearer. The United Modeling Language(UML) will probably end up being the standard notation: .See http://www/dick/samples/uml.html This kind of diagram is not difficult to do in code if you omit the arrow heads and always put the parent above the child. .See http://www/cs202/src/inheritance.cc .Open The Rules of Inheritance . Semantics A derived class inherits all `public` data and functions from its base class. A derived class can not inherit the constructors and destructors of its base/parent class. Typically you have to rethink construction and destruction. They also have the wrong names! However Destructors are also called automatically. It is easy to derive a new constructor from the Base like this: .As_is Student::Student(string s, string n, string d):Person(s,n,d){GPA=0.0;} .See http://www/cs202/src/ex9a.cc The general syntax is: .As_is Derived::Derived(formal arguments):Base(actual Arguments){added} A derived class does not get access to its base class's private data and functions. This would lead to breaches of encapsulation. protected::=members of a class that can be accessed by that class and classes derived from it only. A base class can declare certain data and functions to be `protected`. Protected data and functions can be accessed by objects and functions in derived classes - but there are some rules that make sure that you can not as a result get at private data and functions: .See http://www/dick/examples/protected.cc A derived class can add new functions and data to its base class. A derived class can change the meaning(implementation) of functions. This is called over-loading or over-riding functions in the base class. It is difficult for a derived class to `remove` a function that it's base class defines. All you can do is overload the base function with a function that (1) does nothing, or (2) gives an error message. If you want this effect it may mean that the two classes should share some common parent, or perhaps your choice of child and parent was backwards. A single base class can have to any number of derived classes. Each can add its own functionality and data to the common base class. A class can be both a parent and a child at the same time. You can derive a new class from one that was derived from another one: for example you could derive a Student_intern from a Student and Student from Person. In a complex program you end up with a whole `hierarchy` of classes. In a complex project you must make time early on to plan a stable hierarchy. This takes some thought, experimentation, and discussion: Is A special kind of B? or is B a special A? or do A and B share some common features C? A well thought-out hierarchy can make a set of programs easy to develop. A badly thought out hierarchy can make the work harder. .Box Note Luckily human beings seem to be habitual makers of classification hierarchies. The idea goes back to Plato and Aristotle in Ancient Greece. Indeed most of Aristotle's extant works spend their time setting up large (and boring) hierarchies. People sell ready-made hierarchies of classes. The commonest of these describe the attributes and behavior of objects on a graphic display: Window, Button, Menu, Icon, and so on. Typically when you buy a Visual C++ you are getting C++ with such a hierarchy and some powerful tools for constructing new classes graphically from old ones. These are not free. Object-oriented languages like Java and Smalltalk also come with ready made hierarchies of useful classes. .See http://www/dick/samples/java.class.tree.html The Java class library is free. .Close.Box .Open Syntax derived_class_declaration::= class $derived_class_name : public $base_class_name { $added_members }; derived_class_name::=`any identifier`, But its good style to put a capital letter first. base_class_name::=`any identifier that has been declared to be the name of a class`. added_members::=`a set of public, private and protected declarations`. Members can be data or functions or anything else. Notice the new use of the reserved word: "public" and the position of the `colon` before the "public". . Syntax Exercise Which of the following correctly derives class Lion from class Animal .As_is class Lion { public Animal animal; ... }; .As_is class Lion public : Animal { ... }; .As_is class Lion : public Animal { ... } .As_is class Lion :: public Animal { ... }; .As_is class Animal : public Lion { ... }; Think about how this should be written and the follow this link to .See Answer to exercise .Close Syntax . When to use inheritance Before you derive a new class `D` from a base class `B` ask yourself the following questions: .Net Is each D a special kind of B? Is every D automatically a B? Is it impossible to have a D without also having a B? Is there exactly one B associated with each D and vice-versa? If an object is a D, is it always a D? If an object is a B but not a D, does it never become a D? Are you sure that the B is not really a part of D? Does each D behave like a B? Are D's and B's created and destroyed simultaneously? Are there always more (or the same number) of B's than D's? D isn't a particular instance of a template B<...>, is it? Are You sure that B and D are not derived from a common base? .Close.Net If you answer: "yes, because...." to all of these you can be sure that the `D`s should be derived from the `B`s. .Close Some Rules of Inheritance .Open Multiple Inheritance In C++ we can derive a new class from any number of parents. For example, if Student is the kind of Person who studies and Teacher is the kind of Person who teaches a class, and Employee is the kind of Person who is paid, then we might derive Student_assistant from Student, Teacher, and Employee. A student Intern might be derived from Student and Employee. .As_is class Student_assistent .As_is : public Student, public Teacher, public Employee { .As_is //constructors and destructors .As_is //special features of a student assistant .As_is };//class Student_assistent Faculty might be derived from Employee and Teacher, but not from Student. This is called `multiple inheritance`. Inheriting several non-overlapping interfaces for example is simple and useful. General multiple inheritance is a controversial idea. There are conceptual problems when a class inherits overlapping members(functions and data) from different classes. . Overlapping Functions For example, If you derive a class `D` from two base classes: `B1` and `B2` .As_is class B1 {...}; .As_is class B2 {...}; .As_is class D: public B1, public B2 {...}; and both B1 and B2 have a public function `f`, but `D` does not, then you can not tell if `d.f()` is really .As_is d.B1::f() or .As_is d.B2::f() This may be spotted by the compiler... but even if it is not, it is something to be avoided. . Overlapping inheritances Worse, if B1 and B2 are also derived from a third base class `A`: .As_is class A {...}; .As_is class B1 : public A {...}; .As_is class B2 : public A {...}; .As_is class D: public B1, public B2 {...}; then how many `A`s are there in a `D`? Does each B have an A that is hidden in a D? Or is only one A hidden in D? In C++ the default is for D to have an A associated with B1 and another distinct A associated with B2. However, it is possible for B1 and B2 to be defined so that they will share a single A whenever they are both base classes for a derived class like D: .As_is class A {...}; .As_is class B1 : virtual public A {...}; .As_is class B2 : virtual public A {...}; .As_is class D: public B1, public B2 {...}; . Inheritting a Set of Function Headers One case of multiple inheritance that is useful and uncontroversial. We often have a single abstraction and two or more different ways to implement it. The book showed you a stack implemented by an array and another implemented by a linked list. If you check you will find that the specification (.h) files are almost identical. The private parts differ. The public parts are almost identical. . Interfaces The public part acts as socket defining how the class can be used. We use the word "interface" to describe this part of a class when only functions are public and so all variables are private. If we extract the public member functions and put them in a separate class then we have an interface class: interface::=a class of public member function prototypes We can then write the $interface for a set of classes once and derive the implementations from the common interface: .As_is class interface_name { .As_is public: .As_is //common function prototypes .As_is };//end interface_name .As_is class implementation1_name: public interface_name{ .As_is private: .As_is //private data storage for first implementation .As_is };//end implementation1_name .As_is class implementation2_name: public interface_name{ .As_is private: .As_is //private data storage for first implementation .As_is };//end implementation2_name The implementations of the functions would be listed like this: .As_is Type implementation1_name::function_name(arguments) {...} .As_is Type implementation2_name::function_name(arguments) {...} The classes and functions would probably be in different header and .cc files and compiled into the library for efficiency. A program can be written to call precisely the functions in the `interface`. Objects are declared using the different implementation classes. It is easy to switch between implementations - especially if you use a 'typedef' .See http://www/cs202/typedef.html statement to associate a name with a particular implementation class: .As_is typedef implementation_1 my_favorite_implementation; This is like declaring a const - only we here declare our data type. The is no problem with defining a class by combining two or more non-overlapping interfaces with some private data representing the internal state. . Summary With the exception of inheriting interfaces it might be best if you don't use multiple inheritance until you have had some experience! .Close Multiple Inheritance .Close Inheritance .Open Polymorphism polymorphism::=Greek(`many shaped`). Polymorphism is a very powerful idea. In a polymorphic programming language the program would efficiently and invisible select the correct functions to apply to each object. This would allow sever possibilities which I'll take in turn. . Polymorphism and Templates A template creates class and functions that will automatically adjust themselves to any type of data that is given them. This is a kind of polymorphism. However the forms that we introduce here can be used in some different ways. . Polymorphism by Ignorance Sometimes we can write code that does not need to know anything about the objects that it is handling: sorting and searching algorithms work an any type of data. However they do need to know how much data they are sorting or searching. There is an old fashioned and disliked way to express the idea of a pointer to an unknown type of data. You declare the pointer like this: .As_is void * p; This means: 'p' is an address (or NULL). If non-NULL it refers to the start of some data. `*p` means nothing! You then manipulate the data one byte at a time. Ugly, messy and dangerous. However, a pointer can pointer to the parent of several objects and we can be sure that it points at data of the parental type and that all the parent's operations apply - even if it actually points at an object of a derived type: The address of a student is automatically the address of a Person as well! A Pointer can act as a surrogate or proxy for an object. This is useful because all pointers are the same size. At the machine level a pointer is just an address of a place in RAM. All addresses take op the same number of bits. As a result we can declare and manipulate arrays of pointers to objects even if (1) we are not sure what objects we are pointing at, and (2) the pointers are pointing at different types of object. We will find a neat way to use this freedom when all the different types of object are derived from a common base class. . Polymorphism by Overloading You have already met the idea that "+" is polymorphic: it can add two integers, two floats, two doubles, two chars, .... Each time the code at the machine's level is different but the C++ symbol is the same. A symbol that has multiple meanings is said to be overloaded. The C++ compiler looks at the context of the symbol to determine what you mean by it. You should remember that .As_is 1/2 is 0 but .As_is 1.0/2 has the value 0.5. You can also overload functions - one name with different arguments. You can even add further meanings to the operators in C++. We don't have time to do this but it is not as hard as you might think. Suppose that and Animal is either a cat or a dog. Then we know that every animal makes a noise and needs feeding. Further we know that dogs bark and cats mew. We could encode this in C++: .As_is class Animal { ... make_noise(){...}; name()...}; .As_is class Cat: public Animal{ .... make_noise(){ /*Meou*/}} .As_is class Dog: public Animal{ .... make_noise(){ /*Woof*/}} Notice that this is like (but not the same as) having two implementations of an abstract Animal. Now this means that the `compiler` will recognize and compile in the correct operations in the following: .As_is Animal a; a.name(); a.make_noise(); .As_is Dog d; d.name(); d.make_noise(); .As_is Cat c; c.name(); c.make_noise(); Because Cat and Dog are both special kinds of Animals, the Animal operation on 'name()' applies to `c`and `d` as well as `a`. This is the first kind of polymorphism: Operations apply to objects of different shapes that are extended from some common core. Secondly, the compiler selects the right operation for making noises for the declared type of the data to which it is applied. Consider the following code: .As_is Animal *p; .As_is p=new Dog(...); // *p is a Dog but p is an Animal's address .As_is p=new Cat(...); // *p is a Cat but p is an Animal's address .As_is p=new Dog(...); // *p is a another Dog As the program runs the kind of Animal stored in an element in storage pointed at by `p` changes. Sometimes `*p` is a Dog and sometimes `*p` is a Cat... even tho' `p` is always an `Animal*'. So the compiler won't be able to figure out what this means: .As_is p->make_noise(); in terms of Cat and Dog. It gives up and uses .As_is p->Animal::make_noise() whether p points at a Cat or a Dog. To make a C++ program pick the right method (Cat or Dog) at runtime using the `thing pointed at` and not the `pointer itself` to determine what to do. This is called: `dynamic dispatching`. This is not as efficient as compile-time `dispatching` shown above. C++ provides it as a special option in a class declaration called a `virtual function`. In C++ we get it by putting the word 'virtual' in front of the function declaration... like this: .As_is class Animal { ... virtual make_noise(){...}; name()...}; .As_is class Cat: public Animal{ .... make_noise(){ /*Meou*/}} .As_is class Dog: public Animal{ .... make_noise(){ /*Woof*/}} As the program runs the code for .As_is p->make_noise() is more complex. It tests the type of the object that a points at and selects: .As_is p->Animal::make_noise() .As_is p->Cat::make_noise() .As_is p->Dog::make_noise() depending on the type of `*p`. . An Example A base class called `B` has a function 'f()' that outputs 'B' and a derived class `D` has a function with the same name that outputs 'D': .As_is #include .As_is class B{ public: void f(){cout <<"B"; } }; .As_is class D: public B{ public: void f(){cout <<"D"; } }; .As_is main(){ .As_is B b; D d; .As_is b.f(); d.f(); d.B::f(); .As_is } outputs 'BDB'. So the effect of `f` on an object fits that object's type. The compiler sorts this kind of `polymorphism` out, before the program starts running. The program (once running) has no decision to make. It has been told which function is which. This works when there are several different derived classes. .As_is #include .As_is class B{ public: void f(){cout <<"B"; } }; .As_is class D1: public B{ public: void f(){cout <<"D1"; } }; .As_is class D2: public B{ public: void f(){cout <<"D2"; } }; .As_is main(){ .As_is B b; D1 d1; D2 d2; .As_is b.f(); d1.f(); d1.B::f(); .As_is d2.f(); d2.B::f(); .As_is } outputs: "BD1BD2B" -- again try this out. Now try the following main program in place of the above: .As_is main(){ .As_is B* p; .As_is p = new D1; p->f(); p->B::f(); .As_is p = new D2; p->f(); p->B::f(); .As_is } It will compile because the address of a D1 (new D1) is also the start address of a B - because each D1 is a B with some added data. Similarly `new D2` is also an address of a B. Thus the pointer `p` is `polymorphic` in the sense that it can point at objects of three different types: B, D1, and D2. It can even extract public data from B part of objects of these three types. We get a surprise when we run the above code however because the indirect access to functions with -> is not `polymorphic`. We don't get "D1BD2B". Instead we get "BBBB". The compiler compiles 'p->f()' without trying to find the previous assignment to 'p' - it may be determined at run time: .As_is if(user_input.indicates_d1()) p=new D1; else p=new D2; So the compiler uses the declared type of p (B*) and deduces that this is pointing at a B, and gives us B's function. We could program round the above. But it gets worse... suppose we have an array of items each either being a D1 or D2. We might send a pointer down the array - and we would like it to treat each item as itself not a B! The same thing happens if the D1s and D2s are in a List, Stack or Queue, or any other data structure -- we want iterators to be declared so that that they refer to the general, and yet we want the functions that apply to the thing they specifically point at. . Virtual Functions C++ has a simple way to handle this `indirect` or `dynamic` ` polymorphism`. The word used is rather weird for its purpose: `virtual`. Here are three similar classes but with a simple change: the `f` function is now `virtual`. .As_is #include .As_is class BV{ public: virtual void f(){cout <<"B"; } }; .As_is class D1V: public BV{ public: void f(){cout <<"D1"; } }; .As_is class D2V: public BV{ public: void f(){cout <<"D2"; } }; .As_is main(){ .As_is BV* p; .As_is p = new D1V; p->f(); p->BV::f(); .As_is p = new D2V; p->f(); p->BV::f(); .As_is } The code outputs "D1BD2B" as you might expect. Notice that only the base class (BV) has the word `virtual` in it. virtual_function::=`a member function that is resolved when the program is running, rather than when the compiler is running`. . Arrays of Pointers to Objects The following two examples show how we can have an array of objects of different types, and each one knows how to behave without a single case or if. This array is effectively a mixture of D1s and D2s with each automatically doing its own thing. .As_is main(){ .As_is BV *a[]={ new D1V, new D2V, new D2V, new D1V}; .As_is for( int i = 0; i < sizeof(a)/sizeof(a[0]); i++) .As_is a[i] -> f(); .As_is } By the way, notice these other techniques in the code above: .Net You can create an array of objects with explicit initialization. You can find out the length of an array by using sizeof(array)/sizeof(item) You can have an array of pointers to data of different types but you can't have an array with different types in it. .Close.Net Paul Tonning found a delightful example of this in a text book. It suggested that you could model a bowl of cereal as an array of crispies... each one either going "Snap", "Crackle", or "Pop" as defined. Applying a function to each crisp in turn gets the correct sound. Please try this. Low fat, no calories... .See http://www/dick/examples/rice.cc You might like to think about feeding time at the zoo. Each animal makes its own noise.... and as you go round the cages.... the right noise is produced. . Abstract Classes An `abstract class` is a class can not have objects of its own. An abstract class is like a brochure describe a collection of similar watches. It tells you what you can do with them but if you actually want to tell the time you need a `concrete` watch! In other terms an abstract class can be used to express a `framework` that can be used in a family of related applications. By deriving a specialized version of the abstraction you can get the compiler to generate new versions of a program quickly and easily. An `abstract class` has `concrete` classes derived from it and these can have objects. You can then treat the concrete objects as if they were also abstract ones (which they are anyway). Further - a pointer at the abstraction can actually be pointing at any of the concrete derived class's objects. One abstraction can have many different internal structures - and different performance properties. An abstract class is more complex than an interface. It can have data and also can define the meanings of some functions while leaving others to be defined in concrete classes. The abstract class serves to organize a set of functions that are implemented in many different ways. It sets a standard that different implementations must meet. It is like a standard wall socket or jack - nothing happens unless a working device is plugged into it. It is nice to be able to express an abstraction when we are programming a complex problem. Several object-oriented languages allow you to define an abstract class or an `implementation` and derive from it multiple implementations. In C++ you (1)make all the public functions virtual. This makes sure that the correct implementation is always chosen. The compiler can sort out direct reference before the program starts. The virtual functions will figure out the rest dynamically (as the program runs). (2) make sure that it is impossible to create objects that are in the abstract class, except by declaring one of the implementations. The syntax is odd. (1) all functions in the abstract class must be declared as virtual. (2) at least one function is declared as being `equal to zero`! .As_is class Animal{ .As_is public: .As_is virtual int legs()=0;//this is not a mistake! .As_is virtual void feed(Food);//output a noise? .As_is ... .As_is }; The function 'legs() above is said to be a "pure virtual function'. In Animal above the meaning of feeding an animal and the number of legs it has are `deferred` to a derived classes: .As_is class Lion : public Animal { .As_is public: .As_is virtual int legs(){return 4}; .As_is ... .As_is }; .As_is Class Snake: public Animal{ .As_is public: .As_is virtual int legs(){return 0;} .As_is }; .As_is ... It is now possible to declare Snakes and Lions but we can not declare an Animal. However we can declare variable that points to an Animal and make it point at a Snake or a Lion: .As_is // Animal a; -- illegal .As_is Snake s; // legal .As_is Lion l; // legal .As_is Animal * p; // legal .As_is p=&s; //p is the address of s, *p is s. .As_is p=&l; //p is the address of l, *p is l. We can even declare an array of pointers to animals: .As_is Animal * zoo[]={new Lion("Leo"); new Snake("Rattlebag"),...}; . A Simple Useless example of abstract class .See http://www/cs202/src/implement.cc .Open More Complex Examples . Money This also shows how operators are declared. .See http://www/dick/examples/moneyv.h . Family tree This is an extended example where a set of classes have been created and model the development of a family. Notice how the gender of a person is modeled by their class. Notice how this means that it not easy for a person to change their gender - variables are fixed to their declared type throughout their life. This is also an example of a moderately complex linked data structure. .See http://www/dick/examples/vmf.cc Exercise: The main program records the marriage of a couple and the subsequent birth of twins. Suppose they have now had a boy - add commands to record suitable invented data and then test to see if it has been stored correctly. . Some Advanced Examples Here are a two examples of how virtual functions differ from non-virtual functions: .See ftp://www/dick/examples/vf.cc .See ftp://www/dick/examples/virtual_fun.cc Here are two simple examples of objects that know their own type at run time, as they change. (RTTI): Run Time Type Identification .See http://www/dick/examples/rtti.cc (SCCS): Source Code Control System Strings - a classes that identify the version of code that was used .See http://www/dick/examples/vn.cc .Close More Complex Examples . The Good and Bad News Using this kind of polymorphism - where a base class has more than one derived class and the variations are in virtual functions - means you don't have to write so many 'if()...else...' and 'switch(...)...' statements in your code. This makes C++ code smaller than C code in many cases. However in some early projects, people found their compiled programs were much bigger than they expected. They found that their compiler was not using an efficient implementation of their virtual functions. This may not be a big problem with later compilers. .Close Polymorphism . Designing Class Hierarchies There has been a lot written about this. There have been several projects that have had problems later on because they skimped on the thinking involved. There is lots of reading and practice needed before you can claim to be good at this kind of design. .See http://www.csci.csusb.edu/dick/methods.html#Object-Oriented .Close Inheritance and Polymorphism . Answer to exercise They are all wrong. Here is the correct syntax for deriving class Lion from class Animal: .As_is class Lion : public Animal { ... }; (Don't forget the ';' at the end of the class!) .Close Inheritance and Polymorphism .Close Pointers to C++ documentation and help