Default Arguments 1 When declaring a C++ function, you may optionally specify a default value for function parameters by listing initializations for them in the declaration: class Polynomial { public: Polynomial(const string& N = "no name", const vector<int>& C = vector<int>()); ; You may specify defaults for some parameters and not specify defaults for others; however, all parameters w/o defaults must precede those that have defaults. The default value is used if the call does not specify a corresponding actual parameter: Polynomial F("F", vectorofcoefficients); Polynomial G("G"); Polynomial H; Note that the modified constructor now plays the role of a default constructor.
Implicit Inline Functions 2 C++ class member functions may also be implemented within the class declaration: class Polynomial { public: string getname() const { // inline function return Name; ; This may be considered bad practice since it exposes the details of the implementation to the user of the class. However, this has an interesting side effect. Functions implemented within the class declaration are said to be inline. The C++ compiler may optimize the compiled code by replacing calls to an inline function with the (suitably modified) function body, eliminating some work on the runtime stack.
Explicit Inline Functions 3 An alternative is to specify the function is to be inlined by adding syntax to the function implementation: // Polynomial.cpp #include "Polynomial.h" inline string Polynomial::getName() const { return Name; This has the same effect, but does not expose the implementation in the header file. Note: in any case, the compiler is free to ignore the request and NOT replace calls to the function with its body.
A Stack Class 4 The following slides present a C++ class implementing a fairly straight-forward linked stack. Since templates have not been introduced, the stack is specialized to hold string objects. Logical organization: mtop Data Next Data Next Data Next See the CS 2604 website for complete code for this example.
private Section 5 The private section of the class encapsulates the node type as well as the top pointer: class Stack { private: class Node { // node type private to Stack public: Node(std::string S = "", Node* N = NULL) { Data = S; Next = N; Node* Next; std::string Data; ; ; Node* mtop; // top-most node in stack
Constructors, Copy & Utilities 6 class Stack { public: Stack(); // empty stack Stack(const Stack& Source); // deep copy support Stack& operator=(const Stack& RHS); bool Empty() const; // true iff stack is empty void Clear(); // delete contents of stack ~Stack(); // destroy stack void Display(std::ostream& Out) const; // good for debugging ; Every container class should provide: - sensible construction options - deep copy support - a destructor Display support helps in debugging. A clear() function is also useful, as are empty/full tests if appropriate.
Core Functionality The Stack provides the usual insertion/deletion/data access interface: 7 class Stack { public: void void std::string ; Pop(); // remove top element Push(std::string S); // insert element at top Top() throw(stackunderflow); // get copy of // top element std::string& Peek() const throw(stackunderflow); // get // reference // to top // element The interface here is somewhat loosely based on that of the STL stack template. There are some interesting design issues
Stack Top() Function The Stack allows the client to obtain a copy of the top element: 8 string Stack::Top() throw(stackunderflow) { if ( mtop!= NULL ) return mtop->data; else throw StackUnderflow(); The interesting decision is what to do if the stack is empty? The problem is that something must be returned. Rather than return an empty string, which does not indicate an error, this implementation resorts to throwing an exception. Alternatives include: - move the return value to a reference parameter and make return type bool - add a bool reference parameter to indicate failure
Stack Peek() Function The Stack also allows the client to obtain a reference to the top element: 9 string& Stack::Peek() throw(stackunderflow) { if ( mtop!= NULL ) return mtop->data; else throw StackUnderflow(); This allows in situ modification of the top element. Again, an exception is thrown if the stack is empty. Alternatives include: - return a const pointer instead of a reference, with NULL signifying failure - add a bool reference parameter or return value to signify failure
Stack Exception Objects 10 Some Stack members may throw an exception. The exceptions are objects of a trivial class declared in the Stack header file: class StackUnderflow {; Alternatives include: - using some standard C++ class or simple type - using a specialized class that incorporates diagnostic data like a string object - using a hierarchy of trivial classes, so that the type of object thrown is the message
Disabling Copying 11 In some situations, it may be desirable to create a class whose objects cannot be copied. The solution is fairly trivial: just make the declarations of the copy constructor and assignment operator for the class private. Any attempt to copy an object will then result in a compile-time error.
Copy Details Objects of a class are copied by the copy constructor if: - the copy constructor is invoked directly - an object is passed by value to a function - an object is returned by value from a function 12 Objects of a class are copied by the assignment operator if the assignment operator is used directly.
Initializer List 13 Class data members that are instances of classes are, by default, initialized by the default constructors for their types. This can be inefficient if a different constructor is subsequently used. A more efficient alternative is to use initializer list syntax: Polynomial::Polynomial(const string& N, const vector<int>& C) : Name(N), P(C) { Here, the copy constructors for the data members Name and P are invoked directly, prior to the body of the Polynomial constructor. There is no longer any need for code in the body of the constructor. The same approach can be used with simple types.
static Members may have data and function members that are declared to be static. 14 A static data member is shared by all the objects in a class. In other words, a static data member is a class variable rather than an instance variable. A static member function is allowed to operate only on static data members.
Example with static Members class Ticket{ public: Ticket() : mid(ticketcount++) { int ID() const {return mid; static int TicketCount() {return ticketcount; private: int mid; static int ticketcount; Ticket(const Ticket& Source) { mid = ++ticketcount; 15 ; Ticket& operator=(const Ticket& Source) { if ( this!= &Source ) { mid = ++ticketcount; return *this; int Ticket::ticketCount = 0; // Ticket.cpp
Final Notes A member function cannot have the same name as a data member. 16 Data members may not be initialized within the class declaration. No initializations are guaranteed for simple types, including pointer and reference types.