Fall 2011
C++ Programming Language
CSC 415 Research Paper
Brandon Hall
C++ Programming Language
History of C++
C++ has evolved from C through a sequence of modifications to improve its imperative features as well as add constructs to support object oriented programming. (Sebesta)The development of the C++ programming language began in 1979 when Bjarne Stroustrup wanted to add Simula features to the C programming language. C was very efficient and flexible, but was lacking the object oriented features of Simula. Simula was the first object oriented programming language; it had the ability to declare classes, objects, methods, and other object oriented features. A few additions to the C programming language include parameter type checking conversion, and most importantly classes. This is why C++ was first called C with classes. The classes of C++ are very similar to that of Simula and Smalltalk. Later on default parameters and overloading of the assignment operators were added to C++. One of the goals of C with classes was that it could be used for every application that C could be used for, so virtually none of the feature of C would be removed, not even those considered to be unsafe. (Sebesta)
The work on C with classes began in April of 1979 in the Computing Science Research Center of Bell Laboratories. Stroustrup was trying to analyze the UNIX kernel to determine to what extent it could be distributed over a network of computers connected by a local area network. (Stroustrup, A History of C++: 1979-1991) However, Stroustrup originally started brainstorming the idea of C++ when he was working on his PHD at Cambridge University. While working on a simulator project he ran into the issue of poor runtime while using Simula. In an effort to not terminate the project he decided to rewrite the project in BCPL which he said “The experience of coding and debugging the simulator in BCPL was horrible.” (Stroustrup, A History of C++: 1979-1991) However the runtime using BCPL was a significant amount better than with Simula. After working on this project he swore to himself that he would never again work on a project with insufficient tools. It wasn’t until 1984 that C with classes finally became C++, with the addition of virtual methods, which provided dynamic binding of method calls. Between 1985-1990 several new version of C++ were released, with C++ 3.0 being released in 1990 to include new features like parameterized types and exception handling. In 2008 C++0x was scheduled to be released, however it wasn't until recently that it was approved internationally, and was given a new name C++11.
Overview of C++ Language design, Syntax, and Semantics
Names, Binding, and Scopes
Names in the C++ programming language are usually a character string used to represent something else. Most of the time the names are identifiers, but operators such as “*” or “&” are also known as names. Names allow programmers to call an entity in a program, by using a name as a replacement for an address. Names help make the program more readable by limiting the complexity of the code. If programmers had to type in an address every time they wanted to access something in memory, the readability of that program would not be very good. There are several rules in C++ that a programmer must remember when creating names. A name should consist of one or more characters, each of which maybe a letter (i.e., 'A'-'Z' and 'a'-'z'), a digit (i.e., '0'-'9'), or an underscore character('_'). (Hekmat, 2005) However the first character may not be a digit and upper and lower case letters are distinct. There are no limits to the number of characters that are used to create a name in C++. C++ also has several reserved words that can’t be used for names.
There are two forms of binding in C++. The first type of binding is Dynamic binding. Dynamic binding is when binding first occurs during run time, or can change in the course of program execution. (Sebesta) In dynamic binding the type of the variable is not specified by a declaration statement, nor can it be determined by the spelling of its name. Instead the variable is bound to type when it is assigned a value in an assignment statement. (Sebesta)In C++ dynamic binding is only supported through virtual methods. Virtual methods define type dependent operations using overloaded methods, within a collection of classes that are related to through inheritance. (Sebesta) One advantage to dynamic type binding over static type binding is the flexibility in programming that dynamic type binding allows. However there are of course some disadvantages to dynamic type binding. The first being that program is more likely to have errors which would make the application less reliable and dynamic binding will also allow the programmer to assign any value to any type. For example if I wanted to assign my name Brandon to a variable that was type integer then I could do so, and the compiler would not detect this as an error. Also in C++ using dynamic type binding, if a programmer sets one variable equal to another variable, the compiler will automatically convert the type of the right hand variable to the type of the left hand variable.
The second type of binding that C++ allows is static type binding. Static type is the more reliable of the two types of binding however, it doesn’t provide as much flexibility as what dynamic type binding provides. Static binding has two types of declaration, explicit and implicit. Explicit type declaration is a statement in a program that lists variable names and specifies that they are a particular type. (Sebesta) An implicit declaration is a means of associating variables with types through default conventions, rather than declaration statements. (Sebesta) However, C++ does not support implicit declarations. As most languages developed after the mid 1960’s require explicit declarations. (Sebesta)
Scope in C++ is used to describe the extent to which a variable, function, class and types are visible to the different parts of the program. In C++ there are four different scopes. Local scope, Function scope, class scope, and file scope. Local scope is within a function or a block of code in a program. (Wang, 1994)A variable is considered to have local scope to the function or the immediate block of code in which it is declared. A local variables a normally automatic, however if a local variable is declared static, then it is not an automatic variable. Instead, it is created and initialized at compile time and keeps its most recent value even after the function or block of code is exited. (Wang, 1994)Function Scope is scope of the entire extent of the function. (Wang, 1994)To use function scope the programmer must use the reserved word "goto" declare that the identifier is available to that particular function. Class scope is scope of the entire extent of the class. (Wang, 1994)Any variable declared inside the class is visible anywhere in the class. The variable is available to other functions or classes declared inside of the parent class. In C++ other classes can be contained inside of a class. File scope is scope within in the same source code file. (Wang, 1994) A global variable is a example of a file scope identifier, and name known from its point of declaration to the end of the source code file. This variable is visible to any function or class declared in the file. However if the programmer declares a local variable with the same name as the global variable then the local variable would be in scope.
Data types
C++ along with most all other programming languages provide a predefined set of primitive data types. The primitive data types are not defined in terms of other types. The most common primitive data types in C++ are integers, booleans, and character types. Integers in C++ could also be declared as a float or a double. The float value is a four byte value, but the double has double the precision of a float by being an sixty four bit value. The selection of a float or a double is important if the application needs to compute something and be extremely accurate. However, the downfall to using a double is that it also takes double the memory. So, if it is not necessary to have the precision of a double then the programmer will probably use a float.
Boolean types in C++ are like just like they are in other programming language. This provides the programmer with the ability to use a true or false value, and only takes up one bit. However, because a single bit of memory cannot be easily retrieved, they are frequently stored as a byte. (Sebesta)The boolean values are also commonly used as flags or switches. For example the programmer may say "While boolean flag = true do something" this loop would be performed as long as that flag is set to true. In C++ numeric values can also be used as boolean values, this is something that C++ based languages like Java and C# didn't inherit from C++. A good programming practice is to use the boolean values, because it makes the application much more readable.
Character values in defined as type "char". A character variable in C++ occupies a single byte of memory which contains the numeric code for that character. (Hekmat, 2005) The code is converted using a numeric coding system, most commonly the ASCII coding system. For example if a char variable was set to value 'b', the 'b' would be converted to a number value of 98. These values are case sensitive, so a 'B' would be a different numeric value. Some Characters may need to be used as literal values. Which means the programmer may not want the numeric value of 'n', but could want it to be used as a nonprintable character to represent a newline in the program. In this case the programmer would type ''\n''.
Arrays in C++ contain elements of the same data type. So when a array is declared of a type it must remain consistent throughout the program. C++ provides the programmer with several different categories of arrays. When an array is declared in a function that is static, it is considered a static array. A static array is one in which the subscript ranges are statically bound and storage allocation is static. (Sebesta)If an array is declared in a function without the static identifier, the array is of type fixed stack-dynamic array. A fixed stack-dynamic array is one in which the subscript ranges are statically bound, but the allocation is done at declaration elaboration time during execution. (Sebesta) C++ also provides support for fixed heap-dynamic array which are similar to a fixed stack-dynamic array, in that the subscript ranges and the storage binding are both fixed after storage is allocated. (Sebesta)
In C++ arrays can be of any data type available in C++. The array is indexed from zero to the size of the array minus one. Not only can C++ have arrays of data types, but since an array is a data type the programmer can also make arrays of arrays. This is called a multi -dimensional array. Arrays are initialized with the compiler setting the length of the array based on the information put into the declaration by the programmer, or the programmer can hard code the size of the array by adding []'s after the name of the array.It is important to remember when programming in C++ that C++ doesn't have a string class. There for all string processing is done by manipulating arrays of characters. (Budd, 2009)
C++ supports both dynamic and static type checking. Depending on the operation being performed, the compiler will determine whether dynamic or static type checking will be completed. If the programmer is working with unions in C++ then dynamic type checking will take place. Since C++ variables are statically bound the variable will be static type checked. However, Dynamic type checking is the preferred method of type checking.
Expressions and Assignment Statements In C++ all four basic arithmetic operations are available. For multiplication the programmer must use the "*" and for division the "/". The order of operation is the same as in regular algebraic expressions, unless otherwise noted by parentheses. When using division in C++ as long as one of the numbers in the operation is a float data type. If both numbers are of int data types then the operations returns an integer with the remainder discarded. For example if the operation was 3/2 and both 3 and 2 are int data types then the value returned would be a 1. 2 goes into 3 one time with a remainder of 1, but the remainder is discarded. If the programmer wanted the remainder returned, they could use the % operator. C++ also has several built in math functions that will perform operations like power, square root, sin, cos, tan, log, and several others.
Like most languages C++ supports a set of operators for its built in types. However, most concepts for which operators are used are not built in types, so they must be represented as user defined types. For example, if the programmer needs complex arithmetic, matrix algebra, logic signals, or character strings in C++ they use classes to represent these notions. (Stroustrup, The C++ Programming Language, 1997) In C++ the programmer can overload a operator such as the +,-,*,/ provided at least one of the arguments is an object of some class. Defining operators for such classes sometimes allows a programmer to provide a more conventional and convenient notation for handling objects than could be achieved using only the basic functional notation. (Stroustrup, The C++ Programming Language, 1997) It is very important when a programmer is working in a team environment, and using overloaded operators to ensure that they use very effective commenting. It is common for programmers working in a team coding environment to work on code that someone else started and it wouldn't be easy without proper commenting to understand the overloaded operators.
Since C++ is a strongly typed programming language, which means that it requires all variables to be declared a certain data type before being used in the programming. There are times that a variable may need to be converted later on in the program. There are two types of type conversions in C++. The first is implicit type conversion, and the second is explicit type conversion. Implicit type conversions are done automatically by the compiler, and are usually performed on arithmetic operands, function arguments, function return values and initializers. (Wang, 1994)For example if a programmer passes a float variable into a function expecting an integer value, the compiler will automatically convert that variable to an integer. Explicit type conversions are done by the programmers using type cast. A type cast would look something like int X (expression). Explicit type conversion can be used on basic type, user defined enum, and typedef names.
Assignment statements in C++ are used to assign a value to a variable. Since C++ is a strongly typed language, the variables have to be assigned a value before they are used in the program. To assign a value to a variable the programmer uses a single equal sign. Because the single equal sign is used for the assignment statement, the programmer must use a double equal sign for arithmetic operation. The double equal sign is also used in relational expressions. Not only can the variable be assigned a single value, but it could be assigned the value of an arithmetic operation. For example the programmer could say X = Y + 10; and this would set X to equal whatever the value of Y is plus 10.
Relational expressions are pretty similar to that of most other programming languages. These expressions are use in conditional if statements. If a programmer wanted to say "if a variable is greater than another variable then do something" they could use the relational expression >. Likewise the less than sign works the same way as the greater than sign. If the programmer wanted to say less than or equal to, then they would use <=. The double equal is sign is use for equality in relational expressions and != is used for not equal to. When the programmer is using floating point numbers with relational expressions, they need to be careful to make sure they don't get a round off error.
Statement Level Control Structures C++ has two different types of control structures, the selection statement and the iterative statement. There are also two different types of selection statements in C++, the if statement and the switch statement. The if statement is initialized by using the key word "if" followed by parentheses with a relational expression inside the parentheses. If there is just one operation in the if statement, then that operation can be coded directly after the parentheses. If there is more than one operation in the if statement then the block of code must be enclosed by curly brackets. The operation in the if statement is performed when the relational operator returns true. The if statement can also consist of an else statement. The else statement are used in the situation that the first condition statement returns false, then the else statement would be performed. If the statement has an if, and else then the else statement comes last. The else statement does not contain a relational expression; it only contains a operation statement. The else statement can have a nested if statement, this works like other languages else if statements. The else operation statement happens when all other if statements return false. An If statements in C++ can also be nested inside of another if statement.
The switch in C++ is sometimes known as a multiple selection construct, it allows the selection of any number of statements or statement groups. (Sebesta) The switch statement consist of a control expression, then case statements with a constant expression inside of each. At the end of the switch statement the programmer can put an optional default statement that is for unrepresented values of the control expression. If the value of the control expression is not represented by a case statement and no default segment is present, then the switch statement does nothing. (Sebesta) The syntax of the switch statement would look something like this.
switch(expression)
{
case constant - expr 1 :
statements
case constant - expr 2 :
statements
default:
statements} The expression of the switch statement is evaluate first, and the value returned from the expression must be represented by one of the integer -valued constant case label. (Wang, 1994) The case labels must be distinct in a switch statement. Fall through is when the statements at the selected case label and all statements under other case labels after it will be executed in sequence. (Wang, 1994) Control structures also use the reserved word break to all the statement to immediately transfer control to the first statement after the current iteration.
C++ has three different iteration statements, the while loop, the for loop, and the do while loop. A while loop in C++ is similar to an if statement in that it test a condition and if it is true, it does something. The difference is that a if statement only does the operation one time, and the while loop does the operation until the condition becomes false. The programmer has to be careful when using a while loop, because they could get into an infinite loop that would never end. So if the condition says while x is < 10 do something, the programmer would want to make sure they add one to x each time through the loop. This way the while loop will stop once x is greater than or equal to 10. When using a while loop the program can experience a off by one error. This error occurs when the programmer mistakenly uses a value that is one more or one less that the correct value. This can easily happen in the relational expression. For example if the programmer say while x > 10 do something, and the condition should have been while x>=10 do something, then the off by one error could happen. These types of errors can be caught by using C++'s exception handling, which will be discussed later on in the paper.
The for loop in C++ is the most commonly used loop in the language. This loop has a initialization statement, and a condition statement, it also increments or decrements each time through the loop. The initialization statement is executed one time, and the operation statement and update expression execute while the condition remains true. (Budd, 2009)The for loop is commonly used for counting as well as performing an operation a specific number of times. It is also not a good programming practice to use the “!=” relational statement to test the end of a numeric range.
The do loop is used in C++ when the body of the loop must be executed at least one time before the condition of the loop is evaluated. Once the body of the loop is executed one time the condition of the loop will then be tested. The syntax of the do loop is :
do
{
statements
}
while(condition);
The do loop in C++ is probably the least commonly used loop, but can be very
useful in certain situations.
Subprograms
Subprograms in C++ are called functions. Functions are a key feature and are very powerful in object oriented programming. Some general characteristics of a function are they each have one entry point, the calling program is suspended during the execution of the called subprogram, and control always returns to the calling or parent program when the subprogram has completed execution. (Sebesta)The function named main would be the entry point of the program. There are no special key or reserved words to indicate that a function is a function. The header of the function in C++ is recognized by context rather than by a reserved word. Function declarations are common in C++ programs, where they are called prototypes. Such declarations are often placed in header files. (Sebesta) Functions in C++ can either do something, or perform an operation and return a value. In C++ a function can call another function inside of itself. For example a function may be performing a calculation and inside of that calculation the function may need the value of five factorial. In this case the current function could call another function that only calculates factorials, and returns that value. Now the current function has the value of five factorial to use in its calculation. A function can also call itself in side of the body of the function; this is called a recursive function. Also, nesting subprograms is not allowed in C++.
Each function has a set of values passed to it by the calling function or program, these values are called parameters. There are five different models for passing parameters in computer programming. The first is Pass - by - value, then pass - by - result, next is pass - by - value - result, then pass - by- reference, and finally pass by name. In C++ the most common form of parameter passing is pass - by - reference. Pass - by - reference is a model for in out - mode parameters. Rather than copying data values back and forth, as in pass - by - value - result, the pass - by - reference method transmits an access path, and usually just an address, to the subprogram. (Sebesta) Pass - by - name is also used in C++, however it's not very common and is only used for generic parameters of generic functions. Pass - by - name is an in out - mode parameter transmission method the actual parameter is textually substituted for the corresponding formal parameter in all its occurrences in the function.
In C++ there are two special types of subprograms or functions, with the first being overloaded functions and the second is generic functions. An overloaded function is a function that already is defined, but performs a different operation based on the arguments given to the function. When a programmer uses function overloading they are adding features to an already defined function. Function overloading is done by defining multiple versions of a function with the same name, but the versions must have different signatures. The function name, the number, order and types of its formal parameters constitute a functions signature. (Wang, 1994) It is important to remember that the return type is not part of the function signature. When the overloaded function is called in C++ the compiler automatically concludes from the actual arguments, the correct version of the function, in the indicated scope, to invoke. (Wang, 1994)
The second type of function in C++ is a generic function. Normally functions are written to work on arguments of specific types. However with a mixture of techniques, it is possible to write a type - independent or generic functions that works for a mass of different types of arguments. (Wang, 1994)A generic function is a function that is declared with type parameters. When called, actual types are used instead of the type parameters. If called without the type parameters, the compiler will try to assume the actual type from the parameters supplied in the function call. (Generic Function, 2011) Generic functions can be overloaded based on the signature or number of the type parameters of the function.
Abstract data types and Encapsulation constructs
Data abstraction is one of the most important components of object oriented programming. An abstract data type is a type that satisfies two conditions. The first condition is the representation of objects of the type is hidden from the program units that use the type. (Sebesta)The second condition is the declarations of the type and protocols of the operations on objects of the type, which provide the types interface, are contained in a single syntactic unit. The types interface does not rely on the represented objects or the execution of the operations. (Sebesta)
C++ has two constructs that are used to simulate abstract data types; the first is the class and the second is the struct. Structs are most commonly used when only data is included. (Sebesta)A class in C++ is a type, to gain access to that class a programmer needs to create an instance of that class. By creating an instance of the class the programmer also has access to all the global variables. C++ also allows the programmer the use of constructors to initialize data members of new objects. (Sebesta) Constructors are called when an instance of the class object is created, and the constructors can be overloaded. Because all objects in C++ must be initialized before being used, all classes in C++ include at least one constructor. If the programmer doesn’t include a constructor the compiler will create a constructor that calls the parent class if there is a parent class. In C++ there are three different visibility possibilities for a class: public, private and protected. These different levels of visibility have to do with the way the class is seen by other entities inside of the program. A public class is visible everywhere inside of the program. A private member is accessible only by member functions and friends of the class. A protected class is similar to a private class, in many ways except derived classes. (Sebesta) Protected features can be accessed by the member functions of all derived classes. However it is best to leave all data private, if the programmer wants to give access to the data only to derived class member functions, them declare the functions protected. (Budd, 2009)
Support for object oriented programming
As I discussed in the history section of this paper, C++ was developed because of the lack of object oriented capabilities of C. Stroustrup found that the object oriented features of Simula were very helpful while programming in Bell labs. C++ was the first widely used object oriented programming language, and is still widely used today amongst many different types of computer programmers. (Sebesta) As stated by Mr. Stroustrup : "object oriented programming is the use of class hierarchies providing polymorphic behavior through some rough equivalent of virtual functions. For proper object oriented it is important to avoid directly accessing the data in such a hierarchy and to use only a well designed functional interface." Inheritance is one of the most important features of object-oriented programming. Inheritance refers to the information received by the derived class from the parent class. The derived class may receive some or all of the member functions and data members from the parent class. If inherited from the parent class the data members must be initialized when the subclass object is created. It is important for the programmer to remember that the inherited class should always be public, however the compiler will allow the program to compile if it is declared private.
Polymorphism is another powerful tool of object oriented programming. Polymorphism is selecting a function among several functions with the same name, by comparing actual types of the parameters. This can be simply described as a set of objects of different classes with similar behaviors. (Budd, 2009) Two important techniques to ensure successful polymorphic transfer are using base type pointer or reference parameters, and using only the uniform public interface. (Wang, 1994)
Concurrency
For the first twenty years C++ was around concurrency (multithreading)in computer programming was not very popular. It wasn’t until 2008 with the release of C++0x that this feature was added to C++. (Budd, 2009) Multithreading is quickly becoming a very important feature of computer programming. With the development of computer hardware heading in the direction of multiple core processors, it is important for the programs to be able to take advantage of those multiple processors. Without the ability of multithreading this would not be possible. Today there is still a lot of learning to be done in this area of computer science. There is a Microsoft library that is available to C++ that helps the programmer with multithreading in C++, that library is called the MFC library. The Microsoft Foundation class library provides support for multithreaded applications. (Multithreading with C++ and MFC) There is also threading interface for UNIX systems call POSIX threads. This interface allows for multithreading in C++ across different UNIX based platforms.
Exception Handling
Exception handling in a programming language is a way for the program to catch an error during execution without the program crashing. C++ uses a form of exception handling called a Try, catch, throw method. The programmer would put a block of code inside the try part of the exception handler, that block of code would then be executed. If the operation ran without error then the program would move on to the next block of code. If the block of code resulted in a error then the program would move on to the catch portion of the exception handler. In this section of code the programmer describes to the program what to do in case of an error. This can be as detailed as what do for a specific error like trying to divide by zero, or as broad as to do the same thing for every error. For example a programmer might tell the program if an error is thrown, just simply print the error out on the console. The key word throw can be used to signal a exception in a condition. Throw indicates that the function exits immediately. However, the function does not go back to the caller, instead it searches the caller, the caller’s caller, and so on, for a handler that tells it how to handle the logic error. (Budd, 2009) Exception handling is probably one of the single most important operations when it comes to the reliability of a program. If a program does not have good exception handling, the program the program is almost sure to crash at some point during operation.
Evaluation of C++ programming language
Readability
C++ is not considered to one of the most readable languages, for several reasons. The first being that it has instances of feature multiplicity, this means that there are several different ways to do one thing. When this is the case, the code can easily become unfamiliar and hard to read. C++ also supports operator overloading, which allows the programmer to change the meaning of commonly used operators to be defined as something else. In this case it is very important for the programmer to implement good commenting. Another important area that can greatly affect the readability of a programming language is the syntax design. If a program has a rich library of reserved word like the ADA programming language, it is known to be more readable than when a programming language has fewer reserved words as in C++. Other issues like case sensitivity can add to the overall complexity of the language and cause it to be less readable. Writability
Writability is a determined by how a program can be written using a particular language. Most of the time if a language is not considered to be a very readable language, the same is probably true for writability. One of the most important features that can make a language be considered not writable is its use of abstract data. With the use of data abstraction a programing language can easily become difficult to write. C++ does however have some characteristics that make it a little more writable than some languages. For example, since C++ has a small library of reserved words, there aren’t as many words for the programmer to remember. Overall, C++ is a complex language and is not known for its ease of writeability.
Reliability
Although C++ is not known for its ease of readability and writeability, it is known to be a fairly reliable programming language. The area where it tends to have some short falls is in safety. Due to the fact that when C++ was developed, it inherited all functionality of C including all the bad features. With that being said C++ has been a very reliable language in the business world, and will continue to be for years to come.
Cost
In general C++ is considered a low cost programming language. Along with reliability, this is the other reason companies prefer C++ to other languages. With C++ being such a widely used language it is relatively easy for a company to get training in this language for its employees, or there is enough information online to get a decent working knowledge of C++. With this being said, it can be fairly inexpensive for a company to get training in C++. Also, the cost to implement the code can be pretty cheap, with there being several open source compilers for free online.
In closing, I would say that C++ overall is a good programming language, I feel like that it has a proven history, and continues to become a better language with each new release. I would recommend C++ for business based applications.
Bibliography
Budd, C. H. (2009). Big C++ 2nd Edition. John Wiley and Sons.
Generic Function. (2011). Retrieved from MSDN: http://msdn.microsoft.com
Hekmat, S. (2005). C++ Essentials. PragSoft.
Multithreading with C++ and MFC. (n.d.). Retrieved from MSDN: http://msdn.microsoft.com/en-us/library/975t8ks0(v=vs.80).aspx
Sebesta, R. Concepts of programming languages (9th ed.). Boston: Addison-Wesley.
Stroustrup, B. A History of C++: 1979-1991. Murray Hill, New Jersey 07974.
Stroustrup, B. (1997). The C++ Programming Language. Addison-Wesley.
Wang, P. S. (1994). C++ with object oriented programming. Internation Thomson Publishing.
Share with your friends: |