C Language 1208539706757125 9
C Language 1208539706757125 9
C Language 1208539706757125 9
C++ was designed to provide Simulas facilities for program organization together with Cs efficiency and flexibility for systems programming.
C++ Features
Classes User-defined types Operator overloading Attach different meaning to expressions such as a + b References Pass-by-reference function arguments Virtual Functions Dispatched depending on type at run time Templates Macro-like polymorphism for containers (e.g., arrays) Exceptions
Example: A stack in C
typedef struct { char s[SIZE]; int sp; } Stack;
Creator function ensures stack is created properly. Does not help for stack that is automatic variable. Programmer could inadvertently create uninitialized stack.
Example: A stack in C
char pop(Stack *s) { if (sp = 0) error(Underflow); return s->s[--sp]; } void push(Stack *s, char v) { if (sp == SIZE) error(Overflow); Not clear these are the only stack-related s->s[sp++] = v; functions. }
Another part of program can modify any stack any way it wants to, destroying invariants. Temptation to inline these computations, not use functions.
Class Implementation
C++ compiler translates to C-style implementation
C++
class Stack { char s[SIZE]; int sp; public: Stack() void push(char); char pop(); };
Equivalent C implementation
struct Stack { char s[SIZE]; int sp; };
Operator Overloading
For manipulating user-defined numeric types Complex c1(1,5.3), c2(5);
Creating objects of the user-defined type Want + to mean something different in this context
References
Designed to avoid copying in overloaded operators A mechanism for calling functions pass-by-reference C only has pass-by-value
void swap(int x, int y) { /* Doesnt work */ int tmp = x; x = y; y = tmp; } void swap(int &x, int &y) { /* Works with references */ int tmp = x; x = y; y = tmp; }
Function Overloading
Overloaded operators a specific case of overloading General: select specific method/operator based on name, number, and type of arguments
void foo(int); void foo(int, int); // OK void foo(char *); // OK int foo(char *); // BAD: return type not in signature
Const
Access control over variables, arguments. Provides safety const double pi = 3.14159265; // Compile-time constant
class bar { // object not modified int get_field() const { return field; } }
Templates
Our stack type is nice, but hard-wired for a single type of object Using array of void * or a union might help, but breaks type safety C++ solution: a template class Macro-processor-like way of specializing a class to specific types Mostly intended for container classes Standard Template Library has templates for strings, lists, vectors, hash tables, trees, etc.
Stack() { sp = 0; } void push(T v) { if (sp == SIZE) error(overflow); s[sp++] = v; } T pop() { if (sp == 0) error(underflow); return s[--sp]; } };
Using a template
Stack<char> cs; // Instantiates the specialized code cs.push(a); char c = cs.pop(); Stack<double *> dps; double d; dps.push(&d);
Display-list example
Say you want to draw a graphical scene List of objects
lines, arcs, circles, squares, etc.
Inheritance
Inheritance lets you build derived classes from base classes class Shape { /* */ }; class Line : public Shape { /* */ }; // Also a Shape class Arc : public Shape { /* */ }; // Also a Shape Shape *dlist[10];
Inheritance
class Shape { double x, y; // Base coordinates of shape public: void translate(double dx, double dy) { x += dx; y += dy; } }; class Line : public Shape { }; Line l; l.translate(1,3);
Line inherits both the representation and member functions of the Shape class
// Invoke Shape::translate()
Implementing Inheritance
Add new fields to the end of the object Fields in base class at same offset in derived class C++ class Shape { double x, y; }; class Box : Shape { double h, w; };
Virtual Functions
class Shape { virtual void draw(); }; class Line : public Shape { void draw(); }; class Arc : public Shape { void draw(); }; Shape *dl[10]; dl[0] = new Line; dl[1] = new Arc; dl[0]->draw(); dl[1]->draw();
draw() is a virtual function invoked based on the actual type of the object, not the type of the pointer
New classes can be added without having to change draw everything code
vptr a b
&Virt::foo &Virt::bar
Cfront
How the language was first compiled Full compiler that produced C as output C++ semantics therefore expressible in C C++ model of computation ultimately the same C++ syntax substantial extension of C C++ semantics refer to the same model as C So why use C++? Specifications are clearer, easier to write and maintain
Default arguments
Another way to simplify function calls Especially useful for constructors
void foo(int a, int b = 3, int c = 4) { /* */ } C++ foo(3) foo(4,5) foo(4,5,6) Expands to foo(3,3,4) foo(4,5,4) foo(4,5,6)
Multiple Inheritance
Rocket Science Inherit from two or more classes: class Window { }; class Border { }; class BWindow : public Window, public Border { };
// Error: ambiguous
A B C
In-memory representation of a C
1. b is a B*: vptr has f(), g() 2. Call C::f( this 2 ) 3. First argument now points to a C
vptr y z
&C::f 2 &B::g 0
Cs vtbl
vptr x vptr y z
&C::f
B in Cs vtbl
&C::f_in_B &B::g
Namespaces
Namespace pollution Occurs when building large systems from pieces Identical globally-visible names clash How many programs have a print function? Very difficult to fix Classes suggest a solution class A { void f(); };
Namespaces
Scope for enclosing otherwise global declarations namespace Mine { void print(int); const float pi = 3.1415925635; class Shape { }; } void bar(float y) { float x = y + Mine::pi; Mine::print(5); }
Namespaces
using directive brings namespaces or objects into scope namespace Mine { const float pi = 3.1415926535; void print(int); } using Mine::print; void foo() { print(5); } // invoke Mine::print using namespace Mine; float twopi = 2*pi; // Mine::pi
Namespaces
Namespaces are open: declarations can be added namespace Mine { void f(int); } namespace Mine { void g(int); // Add Mine::g() to Mine }
Namespaces
Declarations and definitions can be separated namespace Mine { void f(int); } void Mine::f(int a) { /* */ }
Exceptions
A high-level replacement for Cs setjmp/longjmp struct Except {}; void bar() { throw Except; } void foo() { try { bar(); catch (Except e) { printf(oops); } }
C++ IO Facilities
Cs printing facility is clever but unsafe char *s; int d; double g; printf(%s %d %g, s, d, g); Hard for compiler to typecheck argument types against format string C++ IO overloads the << and >> operators cout << s << << d << << g; Type safe
C++ IO Facilities
Printing user-defined types ostream &operator<<(ostream &o, MyType &m) { o << An Object of MyType; return o; } Input overloads the >> operator int read_integer; cin >> read_integer;
Iterators
Mechanism for stepping through containers vector<int> v; for ( vector<int>::iterator i = v.begin(); i != v.end() ; i++ ) { int entry = *i; }
v.begin() v.end()
Other Containers
Insert/Delete from front mid. end random access vector O(n) O(n) O(1) O(1) list O(1) O(1) O(1) O(n) deque O(1) O(n) O(1) O(n)
Associative Containers
Keys must be totally ordered Implemented with trees set Set of objects set<int, less<int> > s; s.insert(5); set<int, less<int> >::iterator i = s.find(3); map Associative Array map<int, char*> m; m[3] = example;
Medium-cost Features
Virtual functions Extra level of indirection for each virtual function call Each object contains an extra pointer References Often implemented with pointers Extra level of indirection in accessing data Can disappear with inline functions
Inline functions Can greatly increase code size for large functions Usually speeds execution
High-cost Features
Multiple inheritance Makes objects much larger (multiple virtual pointers) Virtual tables larger, more complicated Calling virtual functions even slower Templates Compiler generates separate code for each copy Can greatly increase code sizes No performance penalty
High-cost Features
Exceptions Typical implementation: When exception is thrown, look up stack until handler is found and destroy automatic objects on the way Mere presence of exceptions does not slow program Often requires extra tables or code to direct clean-up Throwing and exception often very slow
High-cost Features
Much of the standard template library Uses templates: often generates lots of code Very dynamic data structures have high memorymanagement overhead Easy to inadvertently copy large datastructures
Conclusion
C still generates better code Easy to generate larger C++ executables Harder to generate slower C++ executables
Exceptions most worrisome feature Consumes space without you asking GCC compiler has a flag to enable/disable exception support fexceptions and fnoexceptions