history of c++ 5 1980: c-with-classes developed by bjarne- stroustrup 5 1983: c-with-classes...
Post on 21-Dec-2015
218 views
TRANSCRIPT
History of C++
1980: C-with-classes developed by Bjarne-Stroustrup
1983: C-with-classes redesigned and called C++ 1985: C++ compilers made available
1989: ANSI/ISO C++ standardization starts 1999: ANSI/ISO C++ standard approved
Major Features of C++
Upward compatible with C (almost) All valid C programs are valid C++ programs
First C++ compiler generated C (C-Front) Extends C with object oriented features Compile-time checking: strongly typed
Classes with multiple inheritance No garbage collection, but semi-automatic storage
reclamation.
Hello, world!
Sample #include <iostream.h>
main ( ) { cout << "Hello, world!\n";
} Uses:
cout: a special variable for outputiostream: the package that defines special C++ input and
output features (such as cout).
Basic I/O Conventions
We will look at the basic I/O calls first, so that we can use them as we go along
Basic operators "<<" is used for output
along with the special variable "cout" ">>" is used for input
along with the special variable "cin"
Example
Printing the maximum of two numbers: #include <iostream.h>
main ( ) { cout << "please enter two numbers:";
cin >> v1 >> v2; if (v1 > v2)
cout << v1; else
cout << v2; cout >> " is the largest number.\n";
}
Declarations
Basic declarations just like C int c, d=0;
const int answer = 42; One difference, declarations can appear anywhere
a statement appears, and yield the declared entity. for (char i = 0; n < 256; n++) { ...
can delay declaring variables till neededand often make them constant
(single assignment style)
Basic types
Char (may be signed, unsigned, not necessarily ASCII, though usually assumed).
wchar_t = unicode (10646), length impl dep short, int, long (implementation dependent)
[short | long] unsigned float, double (impl dependent)
boolean (this is not in C!)
Enumerations
enum Token_Value {n1, n2, n3=55}; not really an enumeration in the Ada sense More like a collection of integer constants
An enum type is an integral type and you can do arithmetic on it
All values OK, e.g. 7 is an OK value of type Token_Value for the above declaration.
Pointers
A pointer is a reference to an item in memory Pointer arithmetic allowed, but only within a
single array pointers as in C roughly equivalent to array
references Explicit & and * operators used as in C
References
A reference is a name for an object int i = 1;
int& r = i;int x = r;
r = 2;
i now has the value 2 and x has the value 1
More on References
A reference passed by value creates a call by reference
void increment (int& aa) {aa++;}
void f( ){
int x = 1; increment (x); // x = 2
}
Statements in C++
Generally follow C style nothing much to add
all the oddities of C are imported, e.g. switch (x) {
for (int j = 0; .....) { case 1: ... case 2: ... case 3: ...
}}
Comments
/* any number of lines of code, as in C */
// comment to end of line (like Ada) Note: if you use // for all comments, then /* can be used to comment out a block of code including
all comments
Expressions
Again basically the same as C Same peculiarities
e.g. 3 is an OK statement 3,4 is an OK expression
Functions
Essentially similar to C Prototypes absolutely required
(one of the non-upwards compatibilities) Overloading permitted
but complex because of implicit conversions on input values only
More on Overloading
Five possible levels of matchexact match of types (with only trivial conversions)
Match using promotions (e.g. Bool to int, int to long)Match using standard conversions (e.g. int to double)
Match using user defined conversionsMatch using ellipsis in function declaration
Must be one single match at highest matching level, e.g. 2 matches using promotions plus one
exact match is OK.
More on Overloading
Resolution for Multiple Arguments Find best match for each argument
A function that is a best match for one argument and a better than or equal match for all other arguments is
selected. Otherwise the all is considered ambiguous
Default Arguments
Can have default arguments int f (int m; int n = 0; char *q = 0)
Can only omit trailing arguments Since no named notation allowed for call
Unspecified Number of Arguments
Int printf (const char* ...) allowes arbitrary number of args of arbitrary type
Not type safe Special library functions to retrieve arguments
Macros
Macros available as in C But generally not used in C++
for constants use const for small functions use proper inlined functions
avoid other uses Do NOT invent your own language
#define BEGIN {
Classes
Are used to introduce new data types into a program.
These datatypes are often called objects A class is a collection of named data elements
Two kinds of membersdata members
member functions Public and private part
Example of a Class
class Animal {public:
string getName(); void setName (string);
int getAge(); setAge(int);
private: string *name;
int Age;};
Data members
Class contains a collectoin of data members, the basic data being stored in a class instance.
Each data member is like a traditional field within a struct in C
Data members can be public or private Private members can only be referenced by
member functions Public members can be referenced by client
Note on structs
Structs are allowed in C++ special kind of class by default public
A struct that looks just like a C struct is a class with all public data members and no member
functions defined
Member functions
A member function is ons of the set of functions that can be applied to objects of that class
They appear as fields (function declarations) within the class
You can have zero, one or more The public member functions define the class
interface, and can be accessed by the client.
More on Levels of Access
Public fully accessible to the client
Protected fully accessible to derived class, but private to client
Private accessible only to member functions, and not to derived
classes.
Tag Names
A class is given a tag name The tag name serves as a type specified for the
user defined class. This acts as a C typedef would
Examples Screen myScreen;
Screen *tmpScreen = &myScreen;Screen& copy (const Screen[]);
Member Function Bodies
If body is provided within class definition then it is considered as an inline function
Otherwise provide body in usual manner implicitly takes object used to call it
can reference data members directly by name
Example of Member Functions
class stack {public:
stack ( ) {t = 0;} void push (int x) {stck [++t] = x;};
int pop ( );private:
int stck[20]; int t;
}
Defining Member Function Outside
int stack::pop ( ) { const int tmp = stck[t--];
return tmp;}
Need to specify stack:: to say which instance Can reference stck and t directly
If necessary to reference entire object, usespecial value "this".
Calling Member Functions
stack x;x.push (3);
cout << x.pop (); Use the class name as a prefix
Just as you would refer to a field of a struct Operators can be defined using e.g.
operator+ all operators redefinable, including new, indexing, ...
Mutable data members
If a member function is declared const, then it cannot logically modify the object
But it may need to make modifications to internal data, e.g. Memo functions
mutable data can be modified by constant functions, it is typically private.
Derived Classes
class Employee { string first_name, family_name;
char middle_initial; ...
public: void print () const;
string full_name () const; ...
}
Manual derivation
class Manager { Employee emp;
short Level;public:
void promote ( );}
But Manager is NOT an Employee e.g. Cannot apply Employee functions
Using a Derived Class
class Manager : public Employee { int Level;
public: void print_level ( );
} Now a manager really is an employee
and all employee functions can be used
Virtual Functions
We would like print to automatically do the right thing depending on what it is printing.
virtual void print () const; Now we can override print in derived classes And when print is called, the right one will be
called depending on what type is involved Uses an indirect call through a table
Abstract Classes
Sometimes we have a type which only makes sense if it is derived, e.g.
class Shape {public:
virtual void rotate (int) = 0; virtual void draw ( ) = 0;
... The = 0 makes the member functions, and hence the
class itself abstract Can only be used to derived new classes
Constructors and Destructors
Constructors are member functions returning instances of the class.
Called implicitly or explicitly to initialize Destructors
~Stack ( );special member function in exactly above form
called implicitly when object is destroyedmost often used to free storage
Friends
Class M; Class V { float v[4];
friend V operator* (const M&; const V&;);}
Class M { V v[4];
friend V operator* (const M&; const V&;);}
Multiple Inheritance
Classes can have more than one direct base class class Satellite: public Task, public Displayed {
// ...}
The representation of an instance of Satellite contains instances of the representations of both
Task and Displayed Including two VPTR values pointing to virtual
functions.
Using Multiple Inheritance
An instance of Sattelite can be treated as either a Task or as a Displayed: void f (Satellite& s)
{ s.draw( ); //Displayed::draw ( )
s.delay(10); //Task::delay( ) s.transmit (); //Satellite::transmit( )
} Also a Satellite can be be passed to functions
expecting either a Displayed or a Task
MI sounds nice but ....
The basic efficient model of inheritance uses the prefix trick:
If AA is derived from BB, then The first part of an AA looks like a BB
So SS can be treated as BB with no overhead But this trick does not extend to the MI case
So we need to do something else (indirection, extra offset parameter etc), which may introduce extra
overhead even when MI is not used.
... Replicated Base Clauses
Suppose Task and Displayed are both based on a third class called Link.
Now an instance of Task has an instance of Link And an instance of Displayed has an instance of Link
We know that Satellite has an instance of Task
Satellite has an instance of Displayed So does Satellite have two separate Links?
Disambiguating
Suppose that a Satellite instance wants to call method in Link:
p->Link::next = 0; that won't do ambiguous, which Link?
So we have to disambiguate p->Task::Link::next = 0;
This is the same method we would use if Displayed and Task had common member names
Virtual Base Classes
With virtual base classes we avoid replication: class Storable { ...
class Transmitter : public virtual Storable { ...class Receiver : public virtual Storable { ...
class Radio : public Transmitter, public Receiver { ... In this case an instance of Radio has only ONE
Storable instance. A virtual base class says include at most one of
me in the resulting instance at any level.
What to do if no MI: Mixins
The idea in a mixin that we derive a new class from a single base class, and then include an
instance of the other base class as an explicit data member of the new class.
Now we can define new methods on the new class that provide access to the methods of the mixin
class When calling functions for the mixin class we
have to explicitly name the member.
OO Programming C++ vs Ada
Ada has a more general functional notation func (thisobject, someotherobject, junk)
instead of thisobject.func (someotherobject, junk) Which is nicer?
For a functional view, Ada (e.g. Binary plus) For a strict OO view, C++, emphasizes method/msg
OO Programming Ada vs C++
Ada has only single inheritance Mixins can be used to achieve effect of MI
Programmer is responsible for exact effect of MI C++ has full multiple inheritance
with control over sharing Which is better
big religeous argument. Single inheritance is more pure, less complex, MI is often convenient (e.g. A persistant
B-Tree derived from Persistant, B_Tree)
The Name Space Problem (C)
The problem There is one large global name space
If you have a function push at the global level, then you cannot have a function push in some other file at the
global level Particularly difficult in C where there is no bypassing the
problem except by careful global control of the name space
The Name Space Problem (C++)
We are talking of "traditional" C++ now Problem is not so bad as in C
Because method names are encapsulated withintypes, and so are not part of the one big name space. But type names themselves are still a problem
So are global data (instances) and global functions So even in C++ the tyranny of one name space is a
problem
A Solution for C++
Now we are talking about standard C++ The namespace feature, added quite late in the game is copied from Ada 83 packages (or if you
like the similar structure in Delphi) A namespace allows a collection of declarations
(of any kind) to be grouped together Under a single name, the tag of the name space
Namespaces, an Example
namespace Stack { void push (char);
char pop ();}
The declarations of push and pop are part of the stack namespace
and must be referred to using the notation: stack::push('c');
Using a Namespace
Namespace declaration is placed in header #include "stack.h"
void test_stack(){
Stack::push ('c'); if (Stack::pop() != 'c') error ("impossible");
} The file providing the implementation of the
Stack module will also include the interface.
The Using-Declaration
If we have a name space Stack We can qualify Stack::pop
Or we can use a using-declaration: namespace Parser {
... using namespace Lexer; using namespace Error;
} Now names from Lexer and Error can be used as though
they had been declared directly in Parser.
Comparison with Ada
No real equivalent of with (but we do have use) Qualified notation always required Stack::pop (compare with Ada: Stack.pop)
Still have only one name space for namespace names. This is like Ada 83
But in Ada 95 child units are introduced because of perceived problems in having only one namespace for
package names
Child Units in Ada
package Stacks is .... package Stacks.Debug is ...
auxiliary operations for Stacks (body, but not the spec can see the private part of Stacks). Available for use by a
client (who must explicitly with the child pkg) private package Stacks.Trace is ...
internal operations for Stacks, available only to package Stacks and its other children. Not available for use by
clients
More on Child Units in Ada
A tree of Ada units can represent an entire subsystem or library
For example, the entire Ada runtime library as defined in the RM, is a subtree with package Ada
at the top: package Ada is end;
This package is only for naming purposes Now it is only top level packages which compete
for the main global name space.
Exceptions in C++
An exception represents an exceptional occurrence
Is that the same as an error? Debatable
is reaching the end of a list and blowing up an error is reaching the end of file an error
Generally we prefer to consider exceptions as errors and be pretty firm about it (after all we hate gotos :-)
Throwing an Exception
Exceptions are signalled with throw we throw an object, i.e. an instance of some class
Example: throw Int_overflow ("+", x, y);
Here Int_overflow is a class used to represent an exception, which has an operator name and two
operands, to provide information about the error.
Catching an Exception
To catch an exception we use try-catch: void f( )
{ try {
stuff .... }
catch (Integer_overflow& err) { handle the error ...
}}
Rethrow
In an exception handler (the catch section) We an have the simple statement
throw; The effect is to rethrow the current exception
which will then be caught by the next handler up Stack frames are stripped one by one executing catch
handlers till we find one that matches To catch all exceptions:
catch (...) { // handle every exception
Derived Exceptions
Exceptions are objects of a particular class These classes like any other classes can be
derived from other base classes (or even multiple base classes)
An exception handler for a base class will catch all derived instances
This allows a hierarchy of exceptions, with a single handler to catch, e.g. Posix_Error
where Posix_Read_Error is derived from Posix_Error
Exceptions: Comparison with Ada
Raise and when are just like throw and catch Same replacement semantics
Same model for handling propagation Same model for destructors etc
Big difference: In Ada the exception message can only be a string
In C++ it can be any object at all So C++ is more flexible, but more complex
Generic Programming
Genericity vs Type Extension Consider example of queue
basic abstract queue with no data, extended by adding a data field of appropriate type
basic queue with element of a generic private type, instantiated with the appropriate type.
C++ had only extension, added templates Ada had only generics, added type extension
Both features useful?
Templates in C++
A template takes a type (class) as a parameter template <class C> class String {
struct Srep; Srep rep;
public: String ( );
String (const C*); String (const String&);
C read (int i) const;}
More on String Template
<class C> indicates that this is a template for which a type
argument will be used in the declaration. C can be used exactly like any other type name
To use the template, we simply write:String<char> cs;
String<unsigned char> us;class Chinese_Char { ... chinese characters ...}
String<Chinese_Char> chs; This is automatic instantiation
More on Templates
Can have multiple template parameters ordinary parameters such as ints
template parameters (e.g. Class types) Type equivalence
typedef unsigned char UcharString<Uchar> s4;
String<unsigned char> s5;String<char> s6;
s4 is same type as s5, s6 is different
Error Checking
Templates are syntax checked Some semantic checks can be done when template
is compiled e.g. Cannot assign 7 to a pointer, no matter what it is
pointing to! Some semantic checks can only be done when
template is instantiated template <class C> { .... C.draw ....}
Don't know yet if C really has a draw method!
Function Templates
template <class T> void sort <vector<T>&);
void f(vector<int>& vi, vector<string>& vs) { sort (vi); // sort (vector<int>& vi)
sort (vs); // sort (vector<string>& vs);
Composition of Templates
Default parameters (similar to Ada) Derivation
e.g. Derive a non-template class from a template class Templates can have templates as members
Specialization e.g. Specialize to pointer to void (one copy of code)
then share this common specialization
Ada Generics vs C++ Templates
Ada provides a contract model, ensuring that all possible errors are caught at declaration type
Good partCannot have mysterious type errors at instantiation time
requiring going back to template definition.Allows optional generation of shared code
Bad partNot as flexible, need specialized generic parameters, e.g.
range <> for integers, digits <> for floating point, but no possibility of both (even though both have + - * / etc)
Ada Generics vs C++ Templates
Ada requires explicit instantiation, while in C instantiation is implicit by use.
Good partIt is always clear to the reader exactly when a generic instantiation is being created, and exactly what parameters
are being provided. Bad part
Pain in the neck to have to write all the instantiations More or less reader vs writer but ?????
The Standard Template Library