alu - c++ - good

Upload: rajendra-acharya

Post on 11-Oct-2015

66 views

Category:

Documents


0 download

DESCRIPTION

C++ interview question

TRANSCRIPT

  • Page 1 - 1Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 1

    Unit 1: C++ basics

    C++ FundamentalsAlcatel-Lucent Bell Labs

    Software Productivity & Quality Tools Dept.http://www.stc.lucent.com/~dmm/intro

    C++ basics an overview of the most significant C++ features for C programmers.

  • Page 1 - 2Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 2

    Outline

    C++ as a better C using the C language subset of C++

    C++ for data abstraction defining and using classes

    C++ for object oriented programming most of the system is in classes some classes are defined through inheritance

    These three styles of C++ programming have been in use for many years. C++ code written by experienced C developers is often restricted to the C subset of

    C++. Data abstraction programming is often done in the creation of small reusable C++

    class libraries. Object oriented programming requires some commitment to object oriented analysis

    and design work: it is difficult to simply write object oriented code without doing some planning and preparation.

  • Page 1 - 3Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 3

    C++ is a better C

    Features added to C: better type checking function overloading (several functions with the same name, but

    different arguments) inline functions (increases efficiency of small functions) constants (replaces some uses of C preprocessor; defines a contract

    between function writers and users)

    Using C++ as a better C has a very small learning curve, and some significant benefits. Most C source files can be compiled with a C++ compiler after making some minimal

    changes: C++ requires all functions to be declared before they are used, so some extra

    function declarations (or #includes of header files) might be necessary C++ function definitions use the ANSI C syntax [function arguments are

    declared within the parentheses after the function name] Benefits:

    You dont need to run lint to find functions called with incorrect arguments.

  • Page 1 - 4Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 4

    Better type checking in C++

    The following example C program will compile and link, but it wont work correctly:void stringcopy(s1, s2)char *s1, *s2;{

    while ((*s1++ = *s2++) != 0) {}}main(argc, argv)int argc;char **argv;{

    char *mystring = "a test";char b[50], c;stringcopy(b, mystring); /* this line is OK */stringcopy(b, c); /* error at runtime */stringcopy(b); /* error at runtime */

    }

    Traditional C compilers dont check the number or types of arguments. In fact, since the definition of a function might be done in a separately compiled source file, there is no automatic link between a functions declaration and its use.Some tools (such as lint) can give warnings about these kinds of problems in C programs, but the programmer must have the discipline to use the tools consistently.

  • Page 1 - 5Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 5

    Better type checking in C++

    The C++ version of the program will cause compile-time errors, making it much easier to find bad function calls:void stringcopy(char *s1, const char *s2){

    while ((*s1++ = *s2++) != 0) {}}int main(int argc, char **argv){

    char *mystring = "a test";char b[50], c;stringcopy(b, mystring); /* this line is OK */stringcopy(b, c); /* error at compile time */stringcopy(b); /* error at compile time */return (0);

    }

    In C++, the compiler always checks each function call to insure that the arguments match the declaration. If the function is defined in a separate source file, the file that uses the function still must contain a declaration of the function:

    extern void stringcopy(char *, const char *);int main(int argc, char **argv){

    ....

    stringcopy(b, mystring);....

    }Most programmers who create C++ libraries will build a header file that contains the declarations of multiple functions, so the user of the library doesnt have to type in every function declaration.

  • Page 1 - 6Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 6

    C++ for data abstraction

    The major construct in C++ is the class: a collection of data and functions some members of a class are private

    private data is available only to member functions private functions can only be called by other member functions

    The implementation details of a class are hidden from the class user, who only sees the interface

    initialize

    top

    push

    pop

    3

    71113

    items

    stackPointer

    class Stack

    A class is a packaging technique: a way to combine a data structure and the functions that manipulate it. Classes can be used to implement abstract data types.

  • Page 1 - 7Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 7

    Examples of classes

    class Stack {public:

    /* member functions are declared here */void initialize();int top();int pop();void push(int);

    private:/* class data is usually private */int items[10];int stackPointer; /* the index of the first empty array cell */

    };int main() {

    Stack myStack;myStack.initialize();myStack.push(7);myStack.push(11);int i = myStack.top();myStack.pop();return (0);

    }

    This page shows the declaration of the Stack class. This is similar to the declaration of a C struct, but it contains function declarations in addition to the data declarations. The definitions of the functions of the Stack class are shown on the next page.The declaration of the Stack class is usually put into a .h file (such as Stack.h).The Stack class is used in the main program in this example. The myStack.initialize()function will invoke the initialize() function on the myStack object.

  • Page 1 - 8Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 8

    Examples of classes (continued)/* member functions are defined separately.. .. */void Stack::initialize() {

    /* any data member can be used in the definitionof a member function */

    this->stackPointer = 0; /* stackPointer = 0 is also legal */}int Stack::top() {

    return (this->items[this->stackPointer-1]);}int Stack::pop() {

    this->stackPointer--;return (this->items[this->stackPointer]);

    }void Stack::push(int newValue) {

    /* we should first check for overflow */this->items[this->stackPointer] = newValue;this->stackPointer++;

    }

    This page shows the definitions of the functions declared on the previous page. The variable this is a pointer to an object of class Stack: the object that the function was called with.

    int main() {Stack stk;stk.initialize();return (0);

    }void Stack::initialize() {

    this->stackPointer = 0;// in the call to this function in the main program// above, this will point to stk, and this function// will set the stackPointer field within that// structure to 0.

    }

  • Page 1 - 9Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 9

    What is this?

    Each member function will operate on an object. The actions of the member function can access and/or modify the internal

    state of the object. The internal state is a structure containing the data in the class declaration. Each member function call has an extra function argument: a pointer to the

    internal structure.

    void Stack::push(int newValue) {

    this->stackPointer = newValue;

    }

    void push(struct Stack *this, int newValue) {

    this->stackPointer = newValue;

    }

    Stack my_stack;

    my_stack.push(100);

    struct Stack my_stack;

    push(&my_stack, 100);

    C++:

    C:

    equivalent

    In C++, attributes can be accessed within a member function using the "this->" syntax. A member function is really equivalent to having a C function with an extra argument at the beginning: a member function operates on an object, and the "this" pointer tells which object to operate on.The examples on the previous pages are following a common coding standard: to always use the this-> syntax when referring to data members within a member function. Other coding standards require programmers to use a naming convention to help people who are reading the code distinguish which variables are data members: one common technique is to require all data members to begin with m_ (such as m_items or m_stackPointer).

  • Page 1 - 10Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 10

    What is this?

    A call to a member function puts the pointer to the objects state on the stack, then all of the function arguments.

    The member function can access the contents of the objects internal state using the this-> syntax. The member functions can also call other member functions on the same object using the this-> syntax.

    You dont always have to use the this-> syntax: within a member function, any mention of a data member will automatically be treated as a reference to one of the fields within this.

    initialize

    top

    push

    pop

    3

    71113

    items

    stackPointer

    class Stack

    this->stackPointer

    this->top()

    this->items

    Use "this" to refer to data or functions within the current object

    Within a member function, "this" is usually optional the compiler will figure out that you are accessing some member data when you refer to "items" or "stackPointer" within the member function:

    int Stack::pop() {this->stackPointer--;return (this->items[this->stackPointer]);

    }is equivalent to:

    int Stack::pop() {stackPointer--;return (items[stackPointer]);

    }

  • Page 1 - 11Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 11

    Implementation options

    There are several good alternative implementations of the Stack class (without changing the public interface):

    stackPointer could be a pointer instead of an integervoid Stack::initialize() {this->stackPointer = &(this->items[0]);

    }

    items could be a dynamically allocated arrayclass Stack {public: ....private: int *items;int *stackPointer;

    };void Stack::initialize() {this->stackPointer = this->items =(int *) malloc(10 * sizeof(int));

    }

    The main concept behind data encapsulation: the structure of the data within the class should be immaterial to the user of the class. The class user cant access the data directly if the data is all defined in the private section. The class user can only call the public functions in the class.The author of the class might decide to change the internal data structure and/or the algorithms used in the implementation of the class, but so long as the interface stays the same, the user of the class shouldnt care.

  • Page 1 - 12Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 12

    More implementation options

    The Stack class could be implemented as a linked list:void Stack::initialize() {this->stackPointer = 0;

    }void Stack::push(int newValue) {StackNode *sptr = new StackNode;sptr->value = newValue;sptr->next = this->stackPointer;this->stackPointer = sptr;

    }int Stack::pop() {int retval = 0;if (this->stackPointer != 0) {retval = this->stackPointer->value;this->stackPointer = this->stackPointer->next;

    }return (retval);

    }

    For this code to work, the application needs to have a definition of the StackNode structure:struct StackNode {

    int value;StackNode *next;

    };In C++, a struct is a class with all data in the public section by default.

  • Page 1 - 13Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 13

    Common choices for data abstraction

    In a large project, any interface used by many developers database interface user interface interprocess/interprocessor communication

    One or more experts can build the data abstraction, other programmers can use them.

    the experts worry about the implementation details the other programmers will have an easy-to-use interface it will be easier to change database management systems or user interface

    technology

    Data abstractions are often built by specialists. This is one practical way to leverage the skills of an expert: have him/her create a class that everyone else on a software development project can use.

  • Page 1 - 14Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 14

    C++ constructors and destructors

    C++ class objects can have special initialization and cleanup functions these functions are called automatically at block entry and exit#include #include // the string class has constructors and a destructorvoid f() {

    std::string message("hello, world"); /* message initialized */int len = message.length();int i;for (i = 0; i < len; i++) {

    std::string sub_string; /* sub_string set to empty */sub_string = message.substr(0, i);fputs(sub_string.c_str(), stdout);/* the destructor for sub_string is called

    before the next iteration */}/* the destructor for "message" is called before returning */

    }int main() { f(); return (0); }

    Constructors and destructors will be discussed in more detail in Unit 2.

  • Page 1 - 15Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 15

    Object oriented programming

    C++ supports object oriented programming (but it doesnt force you to program in an object oriented style)

    in an object-oriented system, most of the code is in classes new data types can be built from existing data types (using inheritance) C++ virtual functions allow run-time selection of a function

    In an object oriented program, almost all of the code is in classes. In contrast, it is possible to use data abstraction programming to just create a small set of central C++ classes (less than 20% of the total code), which are used from non-class code that comprise the rest of the system.Object oriented development is more complex, and requires a bigger investment in planning and training. Most of the developers need to have some class authoring skills, and it is necessary to have a good overall object model early in the project that serves as a plan. This can help prevent the creation of spaghetti classes.

  • Page 1 - 16Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 16

    Inheritance

    A derived class has all of the data members and functions of the base class new data and functions can be added base class functions can be redefined in the derived class

    Example: Rental car derived classes: Rental van, Rental sports car common functions: customer_pickup, customer_return, clean, fill_with_gas functions with different implementations for different classes:

    compute_customer_charges, get_daily_cost special functions: is_convertible (special function for Rental sports car)

    Rental car

    Rental van Rental sports car

    Derived classes are sometimes called subclasses. Base classes are sometimes called superclasses.

  • Page 1 - 17Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 17

    Object oriented analysis and design

    Object oriented programming changes the way you do analysis and design since most of the system will be implemented in terms of classes, the

    design process should try to produce high-level class descriptions some techniques and notations: CRC cards, UML class diagrams,

    C++ header files object oriented analysis is an attempt to describe the problem domain n

    terms of classes Why is object oriented programming helpful in many situations? It is easier to

    modify and extend a system that is designed in terms of objects changes are more localized than in structured design data abstractions are easier to use (and reuse) extensions can be made by inheritance without changing existing code

  • Page 1 - 18Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 18

    Summary

    C++ is a versatile programming language that supports three different styles of programming

    its a better C it supports data abstraction it supports object oriented programming

  • Page 1 - 19Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 19

    C++ syntax

    In K&R C, a function declaration merely specifies the return type. If a function is not declared, the compiler assumes that the function returns an int./* C-style function declarations */int strcmp();FILE *fopen();double sqrt();

    In ANSI C, a function declaration can specify the argument types:/* ANSI C-style function declarations */int strcmp(char *, char *);FILE *fopen(char *, char *);double sqrt(double);

    C++ function declarations have the same syntax as ANSI C function declarations.

    K&R stands for Brian Kernighan and Dennis Ritchie the authors of the original C textbook The C Programming Language (Prentice-Hall, 1978).Note that an ANSI C compiler will accept both the K&R C and the ANSI C function declarations. The ANSI C language committee decided to do this so that old C code would be portable to new C compilers.C++ is not backward compatible to C. The main areas where it is incompatible is in function declarations and definitions.

  • Page 1 - 20Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 20

    Overloaded functions

    C++ permits the declaration of several different functions with the same name but different argument types:extern double sqrt(double);extern int sqrt(int);int main() {

    double d1;int i2;d1 = sqrt(2.0); // calls sqrt(double)i2 = sqrt(144); // calls sqrt(int)return (0);

    }

    The C++ compiler follows a complex set of function matching rulesto determine which function signature matches best.

    arithmetic promotions are done first (e.g., char short int long) standard conversions are next (such as int float) finally, user-defined conversions are tried (such as single argument

    constructors)

    One reason that all functions must be declared before they are used in C++ is to support overloaded functions and automatic type conversions in function calls. The C++ compiler needs to know all of the function signatures for functions of the same name that it has to choose from when it tries to determine the right function to call.

  • Page 1 - 21Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 21

    Differences

    There are two special function declarations in ANSI C and in C++:int f(void); /* no arguments */int g(...); /* unspecified arguments */

    The first declaration says that the function never takes an argument. The compiler will give an error message if the function f() is called with one or more arguments.

    The second declaration says that the function can take any number of arguments of any type.

    The following declaration is interpreted differently in ANSI C and in C++:int h();/* this means int h(...) in ANSI C *//* but it means int h(void) in C++ */

    Some C library developers will create header files that contain function declarations that will work with either C or C++, like this:

    #ifdef __cplusplusextern "C" {#endifstruct timeval {

    time_t tv_sec;long tv_usec;

    };

    /* declarations of functions */#ifdef __cplusplusextern int adjtime(struct timeval *, struct timeval *);#elseextern int adjtime();#endif

    #ifdef __cplusplus}#endif

  • Page 1 - 22Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 22

    Function definitions

    In C++, the ANSI C syntax is used in function definitions:/* file openfile.c */#include int openOutputFile(char *filename) {

    FILE *f;f = freopen(filename, "a", stdout);return (f != NULL);

    }

    There are no differences in function definition syntax between ANSI C and C++. ANSI C compilers will accept old K&R-style function definitions.

  • Page 1 - 23Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 23

    More about functions

    In C++, it is required to have a declaration of a function before the function is used./* file addfile.c */#include int main(int argc, char **argv) {

    int sum = 0;FILE *f = fopen(argv[1], "r");char buf[512];while (fgets(buf, 511, f) != NULL) {

    sum += atoi(buf); // line 8}printf("total = %d\n", sum);return (0);

    } The compiler will give an error message for line 8, because the atoi() function

    is not declared before it is used. This error message will go away if we put in #include Some functions are declared in string.h, unistd.h, io.h, and other files

  • Page 1 - 24Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 24

    Class declarations

    A class declaration in C++ is like a structure declaration in C the labels public, private, and protected are added to indicate access rights both function declarations and data declarations are permitted/* file Myclass.h */#include class Myclass {public:

    void setdistance(int); // member functionsvoid setlocation(int);int getdistance();void print();

    private:int distance; // member datastd::string location;

    };

    Dont forget the semicolon at the end of the class declaration

    It is possible to define some functions in the private section, but in that case, they could only be called from other member functions of the same class.It is also possible to define some member data in the public section, but good C++ programmers dont do this. They want the class to encapsulate the data, to prevent it from being modified without any controls.

  • Page 1 - 25Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 25

    Defining member functions

    Each member function must be declared in the class declaration andimplemented in a source file/* file Myclass.c */#include #include void Myclass::setdistance(int d) {

    this->distance = d;}void Myclass::setlocation(char *loc) {

    this->location = loc;}int Myclass::getdistance() {

    return this->distance;}void Myclass::print() {

    printf("distance=%d, location=%s\n",this->distance, this->location.c_data());

    }

    The double-colon operator is called the scope resolution operator in C++. The name before the double-colon is always a class name, and the name after the double-colon is most often a function name. In these examples, this syntax is used to show which class the function being defined belongs to.

  • Page 1 - 26Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 26

    Calling class member functions

    When calling a class member function the class object appears first followed by a dot then the function name and the argument list in parenthesesMyclass loc1;loc1.setlocation("Whippany");loc1.setdistance(12);

    Each member function can access and change the data members in the class object that it operates on.

  • Page 1 - 27Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 1 - 27

    Overloaded operators

    All of the conventional operators can be redefined for class types in C++.

    The operators are redefined by writing a function:int operator==(Myclass m1, Myclass m2) {

    int retval = 0;if (m1.location == m2.location && m1.distance == m2.distance) {

    retval = 1;}return retval;

    }

    Binary operators take two arguments, unary operators take one argument

    You can redefine arithmetic operators, the assignment operator (the first argument must be a class), comparison operators, or any other C++ operator

    Overloaded operators can be called in two ways:Myclass mval1, mval2;....

    if (mval1 == mval2) { // this calls the operator==()// function

    ....

    }if (operator==(mval1, mval2)) { // an uglier way, but

    // still a correct way,// to call the same function

    ....

    }

  • Page 2 - 1Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 1

    Unit 2: Constructors and Destructors

    C++ FundamentalsAlcatel-Lucent Bell Labs

    Software Productivity & Quality Tools Dept.http://www.stc.lucent.com/~dmm/intro

  • Page 2 - 2Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 2

    Constructors

    Constructors are used in four places in C++ defining default values for objects of a class initializing some or all of the data fields of an object making a copy of an object

    this gets called automatically to copy function arguments onto the stack

    conversion of one type to another this is the most mysterious use of constructors: objects are converted

    like magic, sometimes when you least expect it

    All C++ class authors need to know how to define the appropriate constructors for the classes that they build.

  • Page 2 - 3Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 3

    Constructor usage

    class Myclass { .... };extern void f(Myclass mval);Myclass m1;int main() {

    Myclass m2;Myclass m3(38, WH");Myclass m4 = "MH";Myclass m5 = m3;f(m3);Myclass *mptr = new Myclass(450, "CB");m2 = m3;return (0);

    } m1 and m2 use the default constructor m3 uses a constructor that initializes some of the data fields m4 uses a conversion constructor the m5 declaration and the f(m3) call use a copy constructor mptr points to an object allocated and initialized from the heap (dynamic

    memory allocation using the malloc() function)

    An important fact about declarations in C++: declarations of built-in types are just like C, but declarations of class types will cause the compiler to insert calls to a constructor function at the point of the declaration.C++ declarations (unlike in C) that are within a function or a block are not required to be located at the beginning of the block: they can be intermixed with executable statements.Note that there are two equivalent options for the declaration of m4:

    Myclass m4 = "MH";

    Myclass m4("MH");Both of these declarations will cause the one-argument constructor to be invoked.

  • Page 2 - 4Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 4

    Defining constructors

    The constructors used in the previous slide can be declared this way:class Myclass {public:

    Myclass();Myclass(int, const char *);Myclass(const char *);Myclass(const Myclass &);

    private:// private data declared here ....

    }; The name of the constructor is always the same as the name of the class Constructors dont have a return value Some constructors will be generated automatically:

    If you dont define any constructors, you get two generated for free: the default constructor (with no arguments) and the copy constructor (with const Myclass & argument)

    If you define any constructors, the copy constructor will still be generated automatically, but the default constructor will not be generated

    The automatically-generated default constructor will call the default constructor for each data member of the class. For data members that are built-in types (int, char *, double, etc.), the automatically-generated default constructor will leave them uninitialized.The automatically-generated copy constructor will call the copy constructor for each data member of the class. For data members that are built-in types, the copy constructor will copy the bits from one object to another.

  • Page 2 - 5Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 5

    Initialization within a constructor function

    Two ways to write a constructor definition: assignment vs. initialization syntax:#include class Myclass {public:

    Myclass(int, const char *);private:

    int distance;std::string location;

    };Myclass::Myclass(int d, const char *loc) {

    this->distance = d; // assignment syntax examplethis->location = loc;

    } or you can write it this way:Myclass::Myclass(int d, const char *loc) :distance(d), location(loc) // initialization syntax example

    {}

    The assignment syntax version is more readable for C programmers, but the initialization syntax is often the preferred style. In some cases, initialization style is more efficient, and in other cases, initialization style is the only one that will compile.

  • Page 2 - 6Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 6

    The default constructor

    The default constructor is the constructor with no argumentsMyclass::Myclass() : distance(0), location("") { }

    The default constructor is used in four circumstances: when you declare a class object with no arguments

    Myclass m1;

    when you create an object from the heap without giving any argumentsMyclass *mptr1 = new Myclass;

    when you create an array of objects from the heapMyclass *marrayptr = new Myclass[100];

    in the constructor of another classclass Newclass {public:

    Newclass();private:

    Myclass loc;};

    Newclass::Newclass() {// Myclass default constructor// will be invoked before the body// of the Newclass constructorthis->loc.setdistance(35);

    }

  • Page 2 - 7Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 7

    Some simple rules for constructors

    Always initialize every data member in the class in every constructor you can use either assignment syntax or initialization syntax

    C built-in types (int, char*, etc.) dont have default values, so if your class contains an int, make sure you initialize it in every constructor

    In a derived class constructor, let the base class constructor initialize as much as it can

    you will probably need to use initialization syntax If a constructor allocates memory, be sure that the memory is

    deallocated somewhere (usually in the destructor) Classes that allocate their own memory usually define the copy

    constructor, rather than relying on the automatically-generated copy constructor

    It is important to initialize data members in your constructors (especially built-in types like int and pointers) because an uninitialized field in a data structure may cause a failure somewhere else in the class code:

    if you are lucky, the use of the garbage data or pointer will cause the program to stop executing or dump core

    if you are unlucky, the use of the bad data will cause other data within your system to be silently corrupted

  • Page 2 - 8Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 8

    Constructors in derived classes

    class Myclass { .... };class Travelclass : public Myclass {public:

    Travelclass();Travelclass(int d, const char *loc, const char *method);Travelclass(int d, const char *loc);

    private:string transport_method;

    };Travelclass::Travelclass() : Myclass(), transport_method("") {}Travelclass::Travelclass(int d, const char *loc, const char *m) :Myclass(d, loc), transport_method(m) {}

    Travelclass::Travelclass(int d, const char *loc) :Myclass(d, loc),transport_method(d > 100 ? "airplane" : "car") {}

    void main() {Travelclass d1(250, "Boston", "train");Travelclass d2(450, "Columbus");

    }

    This slide shows the syntax for creating derived classes in C++.Constructors are not inherited in C++, but each derived class constructor must specify which base class constructor will be used to initialize the data members in the base class part of the new derived class object. The initialization syntax is used to do the specification of the argument list for the base class constructor.If you dont specify a base class constructor in the initialization list of the derived class constructor, the compiler will invoke the zero-argument (default) constructor in the base class. If the base class doesnt have a default constructor, then you will get a compile-time error when you try to compile the derived class constructor.

  • Page 2 - 9Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 9

    Destructors

    There can many constructors for a class, but only one destructor. You usually dont call a destructor: the call is generated by the C++

    compiler at the end of the block or function (for automatic on the stack objects) in the exit() function (for static objects) when you call the delete operator (for dynamic objects)

    An example destructor:Myclass::~Myclass() { } Note that this destructor doesnt need to explicitly call the destructors for

    any of the data fields in Myclass the compiler will automatically add the destructor calls for any class

    objects contained in Myclass just before the return at the end of the destructor.

    The C++ compiler inserts calls to the default constructor for any object that is going out of scope at the end of a block or function. It is a bad idea to use goto statements that bypass the end of a block that contains the declaration of an object with a destructor: most compilers will give a warning that this might cause problems. You must be very careful with the placement of gotos in C++ functions.

  • Page 2 - 10Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 10

    When should a destructor do anything?

    The main job of a destructor is to release any resources that have been acquired by the object, either in the constructor or in other functions.

    The destructor should: close any files that were opened unlock any databases that were locked free any dynamic memory that was allocated

    Destructors can also contain error printing that can be used to help find memory utilization problems

    you might add instrumentation code to all constructors and destructors to keep a global object count: add one in each constructor, deduct one in each destructor

    Destructors are useful for a bunch of instrumentation functionality, not just the closing of files and the cleanup of dynamically allocated memory.

  • Page 2 - 11Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 11

    Summary

    Constructors are useful for setting initial values and doing dynamic memory allocation in C++ classes

    The default constructor and the copy constructor are automatically generated, but you sometimes need to define your own

    A destructor function should release all of the resources that have been attached to the object in the constructor and in other class functions

  • Page 2 - 12Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 12

    Inheritance and virtual functions

    Inheritance is one way to build new datatypes from existing datatypes building extensions or variations of other C++ classes

    Declaring a virtual function causes the compiler to postpone thebinding of a function call to an actual function definition

    Inheritance and virtual functions make it easier to create flexible object-oriented software

  • Page 2 - 13Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 13

    Inheritance

    You can create a derived class from a base class using inheritance:class BasicEmployee {protected:

    string name, id_number;float salary;float bonus;

    public:BasicEmployee(string, string);void set_salary(float);

    };class ManagementEmployee : public BasicEmployee {private:

    float budget;public:

    ManagementEmployee(string, string);void set_budget(float);

    }; A management employee has all the basic attributes and actions, but also has

    budget information and actions.

    The data structure defined by the derived class will contain all of the data from the base class plus the new data fields defined in the derived class. For example, the ManagementEmployee class will have five data attributes: name, id_number, salary, bonus, and budget.The public interface (the set of public functions) for the ManagementEmployee class will contain all of the functions declared in the base class (except for the constructors and destructors) and the functions that are declared in the derived class. For example, the ManagementEmployee class will have three functions defined: the ManagementEmployee constructor, the set_salary(float) function, and the set_budget(float) function.

  • Page 2 - 14Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 14

    Why inheritance?

    It saves typing There is a single point of change for many basic attributes and actions (so it is

    easier to fix bugs) The structure of the software is now parallel to the structure of the problem

    domain An existing datatype can be extended with new data The new derived class can redefine functions defined in the base class

    class BasicEmployee {public:

    virtual void set_salary(float);....

    };class ManagementEmployee : public BasicEmployee {public:

    void set_salary(float); // this function overrides the basic function....

    };

    Inheritance is useful for putting the common parts of a design in one place. This reduces the chances of mistyping a field name or a function definition that would ordinarily need to be repeated in several structures.Both bug fixes and upgrades to basic class behavior can be handled more cleanly, because all of the common stuff is in one place.Derived classes are often used to add new features to an already-working implementation. The philosophy is: Dont make changes to a working system. Extend the system instead.

  • Page 2 - 15Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 15

    More inheritance examples

    Derived class may reuse some data from the base classclass LocalCall {public:

    char local_digits[max_local_digits + 1];char *get_number() { return &local_digits[0]; }

    };class NonlocalCall : public LocalCall {public:

    char country_code[max_country_digits + 1];char area_code[max_area_code_digits + 1];char *get_number() { more complicated implementation }

    };int main() {

    LocalCall c1;NonlocalCall c2;char *num1 = c1.get_number();char *num2 = c2.get_number();char *num3 = c2.LocalCall::get_number();

    }

    What is going on here? There are two classes defined in this code LocalCall and NonlocalCall. The data section of LocalCall contains a single character array (to hold the telephone numberfor a local call).The data section of NonlocalCall actually contains three character arrays the two arrays specified in the NonlocalCall class declaration plus the array defined in the base class.When you call a member function, the identity of the get_number() function that is called depends on the actual type of the object c1.get_number() will call LocalCall::get_number(), whereas c2.get_number() will call NonlocalCall::get_number().If you define a function in the derived class with the same name as a function in the base class, that base class function becomes inaccessible unless you use the explicit scope in the function call the LocalCall::get_number() syntax.

  • Page 2 - 16Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 16

    More inheritance examples

    A derived class object actually contains a base class objectclass LocalCall {};class NonlocalCall : public LocalCall {};

    5827086local_digits:

    5827086local_digits:

    1country_code:

    908area_code:

    a LocalCall object

    a NonlocalCall object

    A NonlocalCall object contains everything that is in a LocalCall object plus the extra attributes that are declared that are special for the NonlocalCall.Always remember inheritance means there can be both common data and common operations between the base class and the derived class.

  • Page 2 - 17Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 17

    Virtual function syntax

    Any normal member function or destructor can be declared as virtual This declaration changes some of the code generation rules for the

    calls to that function Example:

    class BasicEmployee {public:virtual void set_salary(float);

    };class ManagementEmployee : public BasicEmployee {public:void set_salary(float); // also a virtual function

    // because base is virtual};

    Virtual is a special keyword in C++ -- it triggers a special set of code generation rules for function calls through pointers and references.Virtual is not required it is OK to use inheritance without defining base class functions to be virtual. In some designs, virtual functions arent needed, so C++ gives the developer the option to declare classes that will always use conventional member function calls.Note: in Java, all class member functions are virtual by default.

  • Page 2 - 18Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 18

    Virtual functions

    One important pointer rule in C++: a base class pointer can point to any derived class objectBasicEmployee *bptr1, *bptr2;bptr1 = new BasicEmployee("Aaron Anthony", "1358282");bptr2 = new ManagementEmployee("Betsy Blake", "1484646");ManagementEmployee *mptr1;mptr1 = new ManagementEmployee("Nancy Ng", "1500819");

    The new operator is one way to create a dynamically-allocated object in C++. Remember that new will allocate space for the object, call the constructor, and return a pointer to the new object. Sometime later in the application, someone will have to call delete to free the object.

  • Page 2 - 19Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 19

    Virtual functions

    The C++ compiler treats virtual functions in a special way: if the function is called through a pointer, the code that is generated by the

    compiler will check the actual type of the objectBasicEmployee *bptr1, *bptr2;bptr1 = new BasicEmployee("Aaron Anthony", "1358282");bptr2 = new ManagementEmployee("Betsy Blake", "1484646");bptr1->set_salary(65000.0); // virtual function callbptr2->set_salary(85000.0); // virtual function callBasicEmployee b("Carol Charles", "1653131");b.set_salary(68000.0); // normal function call

    C++ language rules permit a base class pointer to point to a derived class object

    so it is easy to define a set of objects of different types a program might call the same operation on each object, but it will

    actually make calls to different functions for the same operation name

    Polymorphism is the word that is used by many object oriented technology experts to refer to the way that C++ function calls might map to different function implementations.

    this is actually a case of run time polymorphism, because the compiler cant determine which function to call

    This is also referred to as dynamic binding, because the connection between the function call and the code that will be executed is dynamic: determined by the executing program rather than the compilation system (which is the usual case with static binding).Virtual functions calls are translated into a small block of code that determines the correct function to call based on a special internal table that the object points to. There is a small amount of extra execution-time overhead for a virtual function call compared to a regular function call.

  • Page 2 - 20Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 20

    Implementation of virtual functions

    If a class contains one or more virtual functions, each object will contain a special pointer that is initialized in the constructor:

    This virtual function pointer (vptr) will point to a table of virtual function pointers for that class (vtbl) that was set up at compile time

    The code generated for each function call that could be polymorphicwill use the vptr to get to the vtbl to find the right function to call

    Mary :BasicEmployee

    Harry : MgmtEmployee

    Carol : BasicEmployee

    Sarah : MgmtEmployee

    void set_department() {BasicEmployee *eptr;eptr = get_first_empl();while (eptr) {

    eptr->set_salary(x);eptr = get_next();

    }} internal secret

    pointer (vptr)

    pointers toEmployeeoperations

    pointers toManager

    operations

    All of the information needed to implement virtual functions is available at compile time.The vtbl (virtual function table) can be built by the compiler. One vtbl is built for each class that contains virtual functions. It contains pointers to each of the virtual functions, in the order in which the functions are declared in the class declaration.Each constructor will initialize the vptr to point to the correct vtbl.Each call to a virtual function will generate code that uses the vptr to find the vtbl. Then the pointer to the correct function is at an offset within the vtbl that is known at compile time.

  • Page 2 - 21Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 21

    Virtual functions replaceswitch statements

    When are virtual functions useful? applications that work with a family of similar classes

    examples: computer graphics, hardware configuration, process control, inventory, knowledge representation, ...

    in a traditional implementation, there would be a lot of code like this:

    switch (sptr->tag_field) {case BOARD_MAIN:

    initialize_main(sptr);break;

    case BOARD_CHANNEL:initialize_channel_board(sptr);break;

    case BOARD_CLOCK:initialize_clock_board(sptr);break;

    }

    in an OO implementation, this code might look like this:sptr->initialize();// each board class has// its own initialize()// function

    Object oriented programming with virtual functions and dynamic binding has two advantages over traditional coding:

    the code is more compact (and easier to follow) it is much easier to add a new variation (a new graphical object, a new board type, a

    new process element, and so on) without having to find all of the places where the type tag is used in the application

  • Page 2 - 22Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 2 - 22

    When should a destructor be virtual?

    Virtual destructor example: Virtual is required when you might do a delete on a Derived object through a Base*

    the virtual declaration arranges the code generation to get the correct destructor based on the actual type of the object

    int main() {Base *baseptr;baseptr = new Base;....

    delete baseptr;baseptr = new Derived("logfile");....

    delete baseptr;return (0);

    }

    // two classes with related opsclass Base {public:

    virtual ~Base() {}....

    };class Derived : public Base {public:

    Derived(const char *filename) {this->f = fopen(filename, "r");

    }~Derived() { // must close log

    if (this->f != NULL)fclose(this->f);

    }....

    private:FILE *f;

    };

    Virtual destructor declarations are usually made in a base class where the derived classes might contain extra data attributes. The virtual function call mechanism will be described later in this unit: in this case, it ensures that the destructor that is called will be the appropriate destructor for the actual object that was created.

  • Page 3 - 1Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 1

    Unit 3: Inline functions

    C++ FundamentalsAlcatel-Lucent Bell Labs

    Software Productivity & Quality Tools Dept.http://www.stc.lucent.com/~dmm/intro

  • Page 3 - 2Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 2

    Inline functions

    Inline functions are useful they are good for defining tiny functions they can improve the efficiency of a program

    Any function can be defined as an inline function you can make ordinary functions and member functions into inline

    functions the treatment of inline function definitions is compiler-dependent

    the compiler may expand the inline function definition many times in a program at any place where the function is called

    the compiler is also permitted to convert an inline function definition into a static function definition

    be careful with creating too many inline functions: inline expansion of a function and multiple static function definitions can waste a lot of memory space

    Inline function declarations in C++ are sometimes said to be a hint to the compiler. They are never an absolute command to change the code generation technique: many compilers will convert the inline function into a local static function if the compiler thinks it would be better.In C programs, some programmers use preprocessor macros to get the same effect as C++ inline functions. Preprocessor macros arent as flexible as inline functions:

    you can define overloaded inline functions: several inline functions that have the same name but different arguments

    an inline function is treated just like a regular function by the C++ compiler when applying the argument type checking, function matching, and argument conversion rules

  • Page 3 - 3Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 3

    How to write an inline function

    There are two ways to do it use the inline keyword in the function definition put a function definition inside a class declaration#include inline int max(int a, int b) { // ordinary inline function

    if (a >= b) return a;else return b;

    }class Book { // both set functions are inlinepublic:

    void set_author(const std::string &a) { this->author = a; }void set_title(const std::string &);

    private:std::string author;std::string title;

    };inline void Book::set_title(const std::string &t) {

    this->title = t;}

    The second syntax (defining the inline member function outside of the class declaration) is slightly preferred, because the programmer has more control over deciding which order the inline function definitions will appear in the source file.

  • Page 3 - 4Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 4

    Style points for inline functions

    Inline functions should always be defined in a .h file Inline virtual functions are OK It is OK for an inline function to contain if statements and function

    calls, but some compilers dont expand inline functions that contain a loop

    EDG compiler wont inline a function with a loop G++ will inline a loop (with O option) and so will Microsoft C++ (with

    /Ob1 option)

    Why are inline functions usually defined in a .h file? They are much less useful in a .cfile, because they can then only be used within that .c file.

  • Page 3 - 5Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 5

    Accessor and modifier functions

    Many class definitions have accessor functions that retrieve part of the data structure encapsulated by the class:class Book {public:std::string get_author() const;std::string get_title() const;

    private:std::string author;std::string title;

    };inline std::string Book::get_author() const {

    return this->author;}inline std::string Book::get_title() const {

    return this->title;}

    Similarly, modifier functions that set only one data field in the class are easy toimplement as inline functions

  • Page 3 - 6Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 6

    Frequently called functions

    A common procedure for improving performance of an application program is to introduce inline functions

    Look for opportunities to factor an existing function into two parts a simple inline part a more complex non-inline part

    Example: loading a bufferclass Buffer {public:

    void load_value(char c);void dump_buffer();

    private:char buf[512];char *cur;

    };inline void Buffer::load_value(char c) {

    if (cur == &buf[512]) dump_buffer(); // dump_buffer() resets cur*cur++ = c;

    }

    In the example above, the dump_buffer() function wont be called very often. Defining the load_value() function as an inline function ought to result in some execution-time savings.

  • Page 3 - 7Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 7

    Cost-benefit analysis

    Using inline functions is a tradeoff between space and time the code is usually larger (the same code is repeated many times) the execution time is shorter (by avoiding the cost of putting arguments on

    the stack and returning a return value) The benefit of using an inline function depends on 5 factors:

    1. the object code size of the function2. the object code size of the stacking, jumping, and cleanup code3. the execution time of the stacking, jumping, and cleanup code4. the number of places in the program where the function is called5. the average number of times the function is actually executed in a single

    run of the program The space cost is [(1) (2)] (4) The time savings is (3) (5)

    Note that for very small functions (if the quantity (1)(2) is negative), the space cost can be negative.These numbers are sometimes difficult to collect. The values of (3) and (5) require some dynamic analysis: (3) can be measured by running small pieces of code multiple times and measuring the time it takes, and (5) might be determined through the use of some program instrumentation, such as a profiler. (1), (2), and (4) are mostly static information: some compilers, browsers, or other static analysis tools can determine these values.Most developers dont even try to collect and do a thorough analysis of these items, but they use the estimated size of a function and the number of times it will be executed to help select which functions to convert to inline.

  • Page 3 - 8Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 8

    Using an inline function thathasnt been defined yet

    When developing a library, it is important to be sure that the inline functions are defined in the correct order.

    if there is a forward reference to inline function g() in the body of inline function f(), the compiler might have trouble inlining everything

    the compiler might force the generation of a static copy of the function g(), which will be called from each inline expansion of function f()

    the creation of a static copy will occur with the EDG compiler and the G++ compiler

    the Microsoft Visual C++ compiler will still be able to inline function g() in the expansion of function f()

    You should compile your programs with warnings turned on in order to find these problems:

    for G++, compile with -Winline; for EDG, compile with -r

    Note that it is silly to make a const declaration for a non-pointer argument: the function body is manipulating a copy of the argument anyway, so who cares if it is modified?

  • Page 3 - 9Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 9

    Example

    #include class SimpleStr {public:

    SimpleStr();SimpleStr(int str_length);inline void clrbuf();

    private:char *stringbuffer; // pointer to dynamic memory areaint length;

    };inline SimpleStr::SimpleStr(){

    this->stringbuffer = 0;}inline SimpleStr::SimpleStr(int str_length) : length(str_length) {

    this->stringbuffer = new char[str_length];clrbuf(); // forward reference to an inline function - not good

    }inline void SimpleStr::clrbuf() {

    if (this->stringbuffer != 0)memset(this->stringbuffer, 0, this->length);

    }

    Some compilers have trouble with this example. If they are generating some of their internal inline function information in a one pass fashion, then the forward reference from one inline function to another (the SimpleStr(int) constructor calling SimpleStr::clrbuf()) might cause the compiler to generate a static copy of the SimpleStr::clrbuf() function.

  • Page 3 - 10Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 10

    Inline constructors

    Remember that constructors automatically call the defaultconstructor for each data member in a class

    unless you specify otherwise using the member initialization syntax This means that constructors can be deceptively complex:

    class Myclass {public:

    Myclass();private:

    int distance;std::string location;

    };inline Myclass::Myclass() { this->distance = 0; }

    The Myclass constructor will also call the default string constructor on the data member location

    Constructors are almost always more complex that they look. Some software development projects have adopted a no inline constructors rule, because they are afraid that their developers will misguess the space overhead caused by defining inline constructors.

  • Page 3 - 11Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 11

    Inline virtual functions

    It is usually harmless to declare a virtual function to be inline. The compiler will create exactly one non-inline copy of the function (in

    the same object file where it puts the virtual function table for the class)class Employee {public:

    virtual float get_bonus() const;protected:

    float salary;static float bonus_rate;

    }inline float Employee::get_bonus() const {

    return (this->salary * Employee::bonus_rate);}

    However, it is a good idea to have at least one non-inline virtual function. Most compilers will generate the virtual function table in the file where

    the first non-inline virtual function is defined

  • Page 3 - 12Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 12

    Debugging inline functions

    You may decide to cancel expansion of inline functions when you want to use a source-level debugger on your program

    This will permit breakpoints to be set within inline functions How to cancel inlining:

    Microsoft Visual C++: use the /Ob0 option G++: dont compile with the O option EDG: use either +d or --no_inlining option HP aCC compiler: use +d or +inline_level 0 option

    An alternative: you can use the preprocessor to selectively control the expansion of inlines

    see pp. 370-371 of Advanced C++ Programming Styles and Idioms by Jim Coplien for one way to do this

    In the selective inlining scheme, the class developer uses a macro such as INLINE in the definition of the class, and the class user has the option of compiling their code with either

    DINLINE=inline or DINLINE=depending if they want inlining completely on or off, or the developer can insert lines like

    #define INLINE inline#include "Xclass.h"#undef INLINE#define INLINE#include "Yclass.h"

    to have more selective control over inlines in different sections of the application.

  • Page 3 - 13Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 3 - 13

    Summary

    Inline functions are good for simple operations You can sometimes divide an operation into an easy part and a more

    complex part Use compiler options that help find non-inline inlines Inline constructors are more complex than they look Inline virtual functions are OK

  • Page 4 - 1Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 1

    Unit 4: Const and references

    C++ FundamentalsAlcatel-Lucent Bell Labs

    Software Productivity & Quality Tools Dept.http://www.stc.lucent.com/~dmm/intro

  • Page 4 - 2Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 2

    Const

    Const is useful in five places defining arbitrary constants (integers and strings) declaring function arguments that are pointers

    this is the #1 use of const: it is essential for all C++ programmers to learn this use of const

    const member functions a corollary of const function arguments

    const return value from a function (not very important) const data member (not very important)

    All C++ programmers need to understand the meaning of const in function arguments and const member functions (the second and third items on the list above).

  • Page 4 - 3Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 3

    Const declarations

    It is good programming style to use const on declarations of strings that wont change during the program:static const char *filename = "main.c";const char *error_message1 = "can't open file %s\n";

    Const can also substitute for #define for integer constantsconst int maxvalue = 1000;int histogram[maxvalue];

    Normal const declarations have file scope. It is possible to make a const declaration that has class scope, but not all older C++ compilers support this:class Myclass {public:

    static const int bufsize = 256;/* or enum {bufsize = 256}; for older compilers */char bigbuf[bufsize];

    };int bigbuf2[Myclass::bufsize];

    Some C++ programmers prefer to use the preprocessor for defining arbitrary constants in application programs. Preprocessor macros, using the #define syntax, can be used for both char string and integer constants:

    #define FILENAME "main.c"#define ERR_MESS1 "can't open file %s\n"#define MAXVALUE 1000#define MYCLASS_BUFSIZE 256

    The primary advantage of using #define to create these definitions is that it is easy to override the initial values defined in a header file with a new set of values defined within another source file.

  • Page 4 - 4Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 4

    Using const for pointers

    Const is often used to restrict the kinds of operations that can be performed on a pointer. This comes up most often when declaring the arguments to a function:// copy source to resultvoid strcpy(char *result, const char *source) {

    while (*result++ = *source++) { }}// bigptr points to an array of Big objects -- findmatch() finds// the first element in the array where bigptr->key matches valueconst Big *findmatch(const Big *bigptr, int value, int max) {

    for ( ; max > 0; max--) {if (bigptr->key == value) {

    return (bigptr);}bigptr++;

    }return ((const Big *) 0);

    }

    In the first example: The result argument is non-const: the pointer can be used to scribble data in the

    array that the calling program hands to the strcpy function. On the other hand, the source argument is const, which means that the

    implementation of strcpy is not permitted to store anything in the memory region that source points to.

    In the second example: The bigptr argument points to the first item in an array of Big objects. Since this

    is declared as a const pointer in the function definition, the findmatch function is not permitted to modify any of the fields in the Big structures: it can only look at the values.

  • Page 4 - 5Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 5

    Examples where const wont work

    The C++ compiler will give an error message when you use a const pointer incorrectly:// make a string all capitalsvoid capitalize(const char *str) {

    // this should be capitalize(char *str)while (*str) {

    *str = toupper(*str); // compile errorstr++;

    }}// incrementlist() adds one to the key field of all the objectsvoid incrementlist(const Big *bigptr, int max) {

    // this should be incrementlist(Big *bigptr, int max)for ( ; max > 0; max--) {

    bigptr->key++; // compile errorbigptr++;

    }}

    In the first example: The capitalize function is breaking the rules. The str argument is declared as a

    const pointer, but the *str = toupper(*str) statement is assigning a new value to one of the characters of the character array.

    In the second example: The incrementlist function is breaking the rules. The bigptr argument is declared

    as a const pointer, but the bigptr->key++ statement is modifying one of the fields in elements of the array pointed to by bigptr.

    In both cases, the compiler gives an error, which alerts the function authors that they are violating the contract that they have specified for the users of the functions.

  • Page 4 - 6Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 6

    Calling functions withconst pointer arguments

    /* from file string.h */extern "C" {

    char *strcpy(char *, const char *);int strcmp(const char *, const char *);

    }/* file main.c */const char *myaddress = "600 Mountain Ave.";char buffer[100];char *p1 = &buffer[0];char *p2 = &buffer[50];void g() {

    strcpy(p1, myaddress); // OKstrcpy(p2, p1); // OK - can call a function that takes a

    // const char * with a char *strcpy(myaddress, p2); // compile error - strcpy() might overwriteint i = strcmp(myaddress, p2); // OK

    } A const pointer argument is more permissive than a non-const pointer argument: it

    allows the function to be called with either a const or a non-const pointer

    This slide shows the function users side: in this case, the functions that take more const pointer arguments are more open to being called with pointers to either const or non-const objects.For C++ pointers, there are actually 4 different possibilities in the declaration. The use of const determines what kinds of assignments are legal...If the declaration is: Then p = newp is: And *p = c is:

    char *p; OK OKchar *const p; illegal OKconst char *p; OK illegal

    const char *const p; illegal illegalNote that when you use some C/C++ compilers (for example, the GNU gcc/g++ compiler), it is a runtime error to make changes to the contents of a literal string because they are allocated in text space rather than data space. There is still an advantage of using the const char * declaration, because an attempt to modify the string will be a compile-time error.

  • Page 4 - 7Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 7

    Const member function

    A member function always has an extra argument: the this pointer Example of an ordinary member function:

    void Big::setkey(int data) { this->key = data; } in this case, the this pointer is a non-const pointer so the internal

    implementation of this function looks like this:void setkey(Big *this, int data) { this->key = data; }

    But there is a special syntax for accessor functions (functions that dont modify the internal state of the object)

    A const member function has a const at the end:int Big::getkey() const { return this->key; } in this case, the this pointer is a const pointerint getkey(const Big *this) { return this->key; }

    C++ class member functions are always either accessor functions or modifier functions. An accessor function (also known as a const member function) is only permitted to look at information in the objects data structure, but it cant change anything. A modifier function (also known as a non-const member function) can and probably will make changes to the internal state of an object.

  • Page 4 - 8Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 8

    Const checklist

    Look for all arbitrary integer constants consider whether they should be defined with either #define or const int

    Look for literal character strings that will not be modified during the course of execution most of these should be declared as const char *

    Look at all pointer arguments if the function argument points to a region of memory that will not be updated during the execution of the function, it should be changed to a const pointer argument.

    Look at all the member functions if the function never makes any changes to any of the data within the data section of the class, it should be changed to a const member function

    Note that it is silly to make a const declaration for a non-pointer argument: the function body is manipulating a copy of the argument anyway, so who cares if it is modified?

  • Page 4 - 9Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 9

    Returning a const pointer

    There is another situation where const is sometimes used. a function returns a pointer into some private memory space that the calling

    function should not modifyclass Myclass {public:

    const char *datastart() const;private:

    static const int arraysize = 100;char localarray[arraysize];

    };inline const char *Myclass::datastart() const {

    return (&this->localarray[0]);}int main() {

    Myclass m1;strcpy(m1.datastart(), "address"); // compile errorconst char *p = m1.datastart(); // OKreturn (0);

    }

    Normally, the secret internal details within a class are supposed to be completely inaccessible, but sometimes it is efficient and convenient to allow application code to read some of the data within a class structure. It is usually best to use a const pointer rather than an ordinary pointer, so that the application code cant inadvertently modify the internal state of the object.Note that the Myclass::datastart() function has two consts in its declaration: the first const tells the compiler that the pointer that it returns will point to a memory region that shouldnt be modified. The const at the end of the declaration tells the compiler that the implementation of the Myclass::datastart() function will not make any changes to the internal state of the Myclassobject.

  • Page 4 - 10Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 10

    Const data member

    A const data member is member data that must be initialized at construction time and cant be modified thereafter:class Myclass {public:

    Myclass(const char *val);private:

    const int length; // length and data will beconst string data; // initialized in constructors

    };

    Myclass::Myclass(const char *val) :length(strlen(val)),data(val)

    {}

    Const data members arent used very often. They are useful for declaring data fields in the class that are set once in the constructor and never changed: the compiler will be able to enforce the rule that the state is never changed.Notice that in C++ constructors, const data members must be initialized with initialization syntax. Assignment syntax wont work: the value is already const by the time the control flow reaches the opening bracket of the constructor function definition.

  • Page 4 - 11Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 11

    Breaking the rules

    Sometimes it is necessary to use a cast on a function argument. This occurs most often when you need to make a temporary change:int compare_firstname(const char *s, const char *target) {

    const char *p = s;while (isalpha(*p)) p++; // scan to end of the first namechar tmp = *p;*(char *)p = '\0'; // or *(const_cast(p)) = '\0';int retval = strcmp(s, target);*(char *)p = tmp; // or *(const_cast(p)) = tmp;return (retval);

    }const char *names[] = {

    "William Miller", "Lloyd Bentsen", "Jack Kemp","Joe Liebermann", "John Edwards", 0 };

    int main() {int i;for (i = 0; names[i] != 0; i++) {

    if (compare_firstname(names[i], "Jack") == 0) {....

    }}

    }

    C++ shares one important thing with C: it is possible to bend any language rule by using a cast. The cast tells the compiler I know what Im doing... trust me.In this example, the compare_firstname function is implemented using the strcmp function. The compare_firstname function violates the const rules when it overwrites some of the characters in the subject string s but it changes them back before leaving the function. So we say that compare_firstname actually maintains the spirit of the const rule: the state of the memory that spoints to is the same before and after the function call (even though it is temporarily modified in between).It is considered poor C++ coding style to make wholesale use of casts, but this kind of localized const rule violation is usually considered OK. It is very important, however, to make sure that the casts are well documented, so that another programmer can understand the code well enough to not break things later.(Important note: This program might not work correctly when compiled with the GNU g++ compiler. If the program is compiled with standard compile-time flags, the compiler puts any string data (such as the values in the names array) into a read-only memory area. You may get a run-time error when you try to modify this data. There is a workaround with g++ -- compile this source code with the -fwritable-strings flag, which requests that the g++ compiler put the strings in a memory area that can be modified.)

  • Page 4 - 12Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 12

    References

    References in C++ are a way to make an alias for an object. This is most often of some practical use in function argument declaration

    use #1: function arguments that the function will modify use #2: efficiency to avoid making a copy of a large object

    All uses of references other than as function arguments or return values are potentially dangerous

    References have a confusing syntax: the & symbol in a declaration means reference, but the & symbol in a normal C++ expression means address of.References are related to pointers, but a reference cant be a substitute for a pointer.

    the syntax for dereferencing a reference is a lot different than the syntax for following a pointer

    a reference must be set to refer to an item at the point when it comes into scope, and it cant be modified to refer to something else until it goes out of scope and comes into scope again

  • Page 4 - 13Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 13

    Using references in function arguments

    You should use references in function arguments where the value of the argument will be changed within the function and the callingprogram needs the changed valuevoid swap(int &x, int &y) {

    int tmp = x;x = y;y = tmp;

    }

    main() {int one=1, two=2;swap(one, two); // swap() will modify one and two

    }

    The arguments are actually passed as addresses

    Reference argument declarations are relatively common in C++ applications.In the C programming language, function parameters are always passed by value: the value of the argument is copied onto the stack.In C++ you have a choice. Normal C++ arguments are still passed by value, but if the declaration of the parameter in the function definition contains an & character, the argument is passed by reference.This is almost identical to var parameters in Pascal.

  • Page 4 - 14Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 14

    Using references in function arguments// incorrect C code// it swaps on the stack

    void swap(int x, int y) {int tmp = x;x = y;y = tmp;

    }main() {

    int one=1, two=2;swap(one, two);

    }

    // correct C version// it uses call by pointer

    void swap(int *x, int *y) {int tmp = *x;*x = *y;*y = tmp;

    }main() {

    int one=1, two=2;swap(&one, &two);

    }

    In C, we need to use call by pointer which will put the address of the objects on the stack.In C++, call by reference reduces the burden on the function developer and the function user the reference arguments are identified in the function prototype, and the C++ code generation automatically deals with sending the pointers and dereferencing the pointers throughout the

  • Page 4 - 15Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 15

    Const reference arguments

    You can avoid copying large structures on the stack by using a reference argument. If the structure isnt modified by the function, the argument should be const reference./* getloc() doesn't modify the "m" argument */void getloc(const Myclass &m, std::string &s) {

    s = m.getlocation();}void getloc1(const Myclass &m, std::string &s) {

    s = m.getlocation();if (s == "") {

    m.setlocation(default_loc); // compile error}

    } Note: you cant call a non-const member function on an object passed in

    as a const references

    Const reference arguments are a common C++ idiom. They provide a combination of efficiency and syntactic convenience.

    functions could be defined to take a const pointer argument, but the caller needs to remember to use & for the argument in the call, and the callee needs to use * to dereference the argument

  • Page 4 - 16Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 16

    Reference return value

    A function can have a reference return value this can avoid some extra copying work in nested function calls this is useful for some standard functions: assignment, I/O functionsclass Myclass {....

    Myclass& operator=(const Myclass &); // assignment operationfriend std::ostream& operatordistance = m.distance;return (*this);

    }std::ostream& operator

  • Page 4 - 17Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 17

    Reference return value

    The reference return value in the assignment operation makes theexecution of multiple assignments more efficient:main() {

    Myclass m1, m2, m3(35, "Princeton");m1 = m2 = m3;// calls m1.operator=(m2.operator=(m3));

    }

    How does this improve efficiency? It avoids a call to a copy constructor. If the Myclass::operator=() function were to return a Myclass object

    instead of a Myclass reference, the argument to the outer assignment [the assignment to m1] would be a reference to a temporary Myclassobject.

    Instead, it just passes the reference to m3 on to the outer assignment.

  • Page 4 - 18Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 18

    Summary

    Const and references are important things to add to your C++ bag of tricks:

    const is most often used in function arguments references are almost always used only in function arguments and return

    values const is part of the interface definition of a function

    you must check all function arguments that are pointers or references, to determine whether they should be const

    references play two roles they specify arguments which can be modified by the function efficiency they help avoid copying large structures

  • Page 4 - 19Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 19

    Supplementary notes on const

    Question: Which of the following uses of const are OK? Which of them are probably not needed?#include void print_int_value(const int val){ // const value argument

    printf("%d\n", val);}void print_str_value(const char *ptr){ // const pointer argument

    printf("%s\n", ptr);}main() {

    const int one=1; print_int_value(one);const char *one_str = "one"; print_str_value(one_str);int two=2; print_int_value(two);char *two_str = "two"; print_str_value(two_str);

    }

    When const appears in an argument list of a function, you need to think about how this will be interpreted by the users of that function:

    The first const (on the declaration of the argument of the print_int_value() function) is completely unnecessary and somewhat confusing. Dont do this dont define a const value argument.

    The second const is meaningful it says that this function promises not to modify the string that is passed in. This is a very good use of const a const pointer argument.

    The other two consts are OK they are local to a function, so it is up to the developer of that function to decide how to use const.

  • Page 4 - 20Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 20

    Supplementary notes on const

    Question: What happens when you define two similar functions? in this case, it depends on the compiler

    g++ compile -time error or link-time error Sun CC no error: always calls non-const version if both are defined

    #include void print_int_value(const int val) {

    printf("const int = %d\n", val);}void print_int_value(int val) {

    printf("int = %d\n", val);}main() {

    const int one=1;print_int_value(one); // calls the second function!!int two=1;print_int_value(two); // calls the second function

    }

    Can we define two similar functions with different constness of the arguments? It depends. There is a problem for const value arguments.This is one of the reasons why many C++ coding standards say dont define functions with const value arguments.

  • Page 4 - 21Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 21

    Supplementary notes on const

    Question: What happens when you define two similar functions? for pointer arguments, the const is meaningful#include void print_str_value(const char *ptr) {

    printf("const str = %s\n", ptr);}void print_str_value(char *ptr) {

    printf("str = %s\n", ptr);}main() {

    const char *one_str="one";print_str_value(one_str); // calls the first functionchar *two_str="two";print_str_value(two_str); // calls the second function

    }

    On the other hand, two functions with different constness may be defined for functions with pointer arguments but even then, it is not necessarily needed or desirable. If the function is really const (that is, if it doesnt modify the value of its arguments), then it should be defined the first way with a const pointer argument.Note: some compilers will give you a warning on the initialization char *two_str="two. Why?

    What is the type of a literal string? Is it char* or const char *?

  • Page 4 - 22Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 22

    Supplementary notes on const

    Question: Which of the following uses of const are OK? Which of them are probably not needed?#include main() {

    const int array_size=100;char buffer[array_size];char *const buffer_start = &buffer[0];strcpy(buffer_start, "C++ Fundamentals");

    }

    What is *const?? it is the declaration of a pointer that cant be moved the value of the

    pointer is fixed

    Both of these uses of const are OK. The const int within a function is usually fine assuming that the developer of the

    function knows that the value will not be changed after the initialization. In this example, the const int is actually quite useful, because it is permitted to use

    this constant in the declaration of the size of an array. The *const on the buffer_start pointer is a little strange, but OK. It is a bit of local

    documentation by the developer of the function declaring that this pointer will never be moved during the execution of this function.

  • Page 4 - 23Alcatel-Lucent ProprietaryUse pursuant to Company Instructions

    C++ Fundamentals Alcatel-Lucent Bell Labs

    page 4 - 23

    Supplementary notes on const

    Question: What happens when you define two similar functions? in function arguments, the *const is not very useful and it can be confusing#include void print_str_value(const char *ptr) {

    printf("const str = %s\n", ptr);}void print_str_value(const char *const ptr) {

    printf("str = %s\n", ptr);}main() {

    const char *one_str="one";print_str_value(one_str); // calls the first functionconst char *const two_str="two";print_str_value(two_str); // ??? depends on the compiler

    }

    There is a problem for *const arguments. If you define two functions one with a *const argument and one with an ordinary * argument, you will either get a compile-time or link-time error (for example with the g++ com