Welcome to Forumpk.com Mark forums read | View Forum Leaders
Forumpk.com




Tutorials/Software Reviews & Tech Support Tutorials to some often repeated & Need help? Got Computer Issues?

Reply
LinkBack Thread Tools Rate Thread Display Modes
Learn C++ (for Advance Users)
 
  #1 (permalink)  
Old 25-10-2008, 12:36 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Learn C++ (for Advance Users)

What Is C++?

C++ is a general-purpose, platform-neutral compiled programming language that supports various programming paradigms, including procedural programming, object-based programming, object-oriented programming, generic programming and functional programming. Unlike several other programming languages, C++ doesn’t impose a specific programming paradigm on its users. This liberality has two major advantages: it enables reuse of C code with minimal or no modifications at all, and it enables designers to choose the paradigm that suits their needs best.

A Bit of History
As opposed to most commercial programming languages that are designed from scratch, C++ was designed as an extension, or superset, of C. Bjarne Stroustrup started to design C++ in 1979 at Bell Laboratories. At that time, the language didn’t have a special name; it was called "C with classes". C with classes supported object-oriented programming facilities including classes, polymorphism, inheritance and operator overloading (these are discussed in the next sections). In 1983 (and according to other versions, in 1984) the name "C++" was proposed and accepted. The first commercial implementation of C++, cfront 1.0, was released in 1985. Cfront was a C++ to C translator. The intermediary C code would then be compiled to native machine code.

The C++ Standardization
Designing C++ as a superset of C offers several advantages:

Reuse of C code in C++ applications

Efficiency

Platform neutrality

Relatively quick migration from C to C++

Avoiding mistakes that occur with languages that are designed from scratch

However, the dependency on C as the substratum of C++ also incurs certain complexities such as the lack of an automatic garbage collection, widespread use of pointers, unchecked array bounds, the lack of a native string type and cryptic declarator syntax.

C++ is a vendor- and platform-neutral language. It’s defined and maintained by an ISO committee that consists of the delegates from national standardization bodies such as ANSI, BSI Group, DIN and many others. The first C++ international standard was ratified in 1998. It has since undergone two major revisions. The first revision is dubbed "C++03". C++03 includes new libraries for smart pointers, regular expressions, tuples and hashed containers, as well as some bug fixes. The second revision of the C++ standard is taking place in these very days. The intent is to finalize the new standard by the end of 2008, hence the name C++09 (or C++0x).

The ISO C++ standard defines the core language, its standard libraries, and implementation requirements. Standard C++ is often used as common denominator among vendors and platforms. Typically, each vendor extends standard C++ by adding platform-specific extensions (e.g., compiler-specific keywords, code libraries and runtime support for dynamic linking, type-checking and proprietary frameworks). However, it’s possible to develop large-scale applications using pure standard C++ thereby ensuring portability and simplifying future maintenance.
__________________
Reply With Quote
Sponsored Links
  #2 (permalink)  
Old 25-10-2008, 12:39 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

C++ as "Better C"

In the late 1980s and the early 1990s, C++ was primarily touted as an object-oriented programming. Yet even if you use C++ as a procedural programming language, it offers considerable improvements compared to C:

Improved memory management

References

Default parameter values

Better type-checking

Strongly typed pointers

Function overloading

Let’s look at some of these improvements more closely:

Improved memory management. In C, you have to call library functions (malloc(), calloc() and free()) to allocate and release memory dynamically. In C++, you use keywords, not library functions, to manage memory. The C++ keyword new allocates and initializes an object dynamically. Similarly, the keyword delete destroys an object allocated using new. Array allocation and deallocation are performed by new[] and delete[].

User-defined types are first class citizens. C++ allows you to use a struct or a union’s name in declarations and definitions as you would use a built-in type:

Quote:
struct Date
{
int day;
int month;
int year;
};

Date d; //In C, 'struct' is required before Date
void func(Date *pdate); //ditto
Reference variables. C++ supports reference variables. A reference is an alias of an existing object. References are like pointer in the sense that they are bound to an existing object. However, unlike pointers, references cannot bind to a different object once they have been initialized. In addition, syntactically, references look like ordinary objects. Here’s an example:

Quote:
Date date;
void func(Date &date_rd); //func takes Date by reference
func(date); // date is passed by reference, not by value
Default argument values. C++ allows you to declare functions that take default argument values. When the function call doesn’t provide such an argument, the compiler automatically fills in the default value argument at the place of invocation:

Quote:
void authorize(const string & username, bool log=true);//declaration
authorize(user); // using default argument. equivalent to: authorize(user, true);
In the function call above, the programmer didn’t provide the second argument. Because this argument has a default value, the compiler silently inserted true as a second argument.

Static Type Checking. All C dialects predating C99 (K&R C, C89, C94 etc.) allow programmers to call a function that hasn’t been declared. C++, however, doesn’t allow you to call a function before it has been declared. This restriction enables the C++ compiler to check the type and number of each argument. Without mandatory prototypes, not only would your code become brittle and bug-prone, it would be impossible to use reference arguments and default argument values.

In C++, pointers are strongly-typed, which means that you can’t assign one pointer to another, unless they are pointing to objects of the same type, or one of the types is derived from the other. For example, assigning a pointer to string to a pointer to int is illegal because string and int aren’t related types.

Function Overloading. In C, you can’t use the same name to declare two different functions. C++ allows you to do that, though. This is called function overloading. When two functions with the same name but different parameter lists are declared, the compiler checks the arguments passed to a function call to decide which overloaded version should be invoked:

Quote:
//three overloaded versions of a function with the same name
int identify(int ID); //#1
int identify(const char *name); //#2
int identify(const string& name); //#3
//call the function
identify(500) ;//calls #1 because the argument is of type int
__________________
Reply With Quote
  #3 (permalink)  
Old 25-10-2008, 12:42 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

The Structure of a C++ Program

Although many C++ implementations nowadays support dynamic linking, components (e.g., Microsoft’s ATL) or a virtual execution environment (Microsoft’s Managed C++) the C++ standard recognizes only one execution context called a program. A program consists of one or more source files that can be compiled separately. A source file together with all the headers and source files included via the preprocessing directive #include, less any source lines skipped by any of the conditional inclusion preprocessing directives, is called a translation unit. Each translation unit that is compiled successfully produces a binary object file. These object files are subsequently linked into a single executable program. A well-formed C++ program must contain the function main(). main() is traditionally regarded as the program’s entry point. Here is a minimal C++ program:

Quote:
int main()
{}
This program is perfectly valid C++ code but it doesn’t do anything. To get a taste of C++, let’s look at a more realistic example:

Quote:
#include <iostream>
int main()
{
std::cout<<"hello world!"<<std::endl;
return 0; //optional
}
This is the C++ equivalent of the following C program:

Quote:
#include <stdio.h>

int main()
{
printf("hello world!\n");
}
Let’s take a closer look at the C++ example. The first line is a preprocessor directive that #includes the standard header <iostream> in the program’s source file:

Quote:
#include <iostream>
<iostream> contains the declarations and definitions of the standard C++ I/O functions and classes. Following the C I/O model, C++ implementations provide I/O facilities by means of a code library that are linked into the program rather than built-in keywords. After the #include directive, the main() function is defined. Inside main(), the program contains a single line of code:

Quote:
std::cout<<"hello world!"<<std::endl;
Let’s parse it:

std::cout is the qualified name of the standard output stream object, cout. This object is automatically created whenever you #include <iostream>.

The overloaded insertion operator << comes next. The insertion operator is a function in disguise (explained below). It takes an argument and passes that object on to cout. In this case, the argument is a literal string that we want to print onscreen.

The second argument, std::endl, is a manipulator that appends the newline character after the string and forces buffer flushing. Again, a manipulator is a function in disguise.

Finally, the return statement at the end of the program returns the program’s exit status to the hosting environment. A program is executed in the context of a process. Therefore, when the program terminates, the operating system collects the return code of the program. This way, other processes can examine the exit code of the terminated process. By convention, a return statement is placed at the end of a C++ program although you can safely omit it. If you omit the return statement, the program will implicitly return 0 to the hosting environment.

As trivial as this program seems, it exposes some of the most important features of C++. First, you will immediately notice the use objects instead of functions for performing I/O operations. Second, the standard libraries of C++, including <iostream>, are declared in the namespace std (std stands for standard.) Thus, instead of declaring standard functions, classes, and objects globally, C++ declares these entities in a dedicated namespace, thereby reducing the chances of clashing with user code and third-party libraries.
__________________
Reply With Quote
  #4 (permalink)  
Old 25-10-2008, 12:44 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Overloading

The operator << is particularly interesting. It behaves as a function that takes an argument, yet it looks like the built-in left-shift operator. In reality, it’s an overloaded operator. Operator overloading is another fundamental concept of C++. An overloaded operator is a function whose name is an operator. You can override almost all the built-in operators of C++ (+, *, >, ++ and so on) this way. Operator overloading may sound revolutionary and even dangerous at first because it seemingly allows programmers to override the meaning of built-in operators. What’s to stop programmers from defining operator + as the subtraction operator? In reality, C++ imposes certain restrictions on operator overloading. The combination of these restrictions and good object-oriented practices guarantee that this feature makes code uniform and intuitive. Consider the concept of a string. In C, assigning strings with the = operator is not allowed. The C++ std::string class overloads the = operator, allowing you to assign strings. For example:

Quote:
std::string s;
s= "please fasten your seatbelt";
Without operator overloading, the snippet would look like this:

Quote:
std::string s;
s.assign("please fasten your seatbelt");
Operator overloading is most useful in math and science libraries whereby classes replace built-in type.

Overloading in C++ isn’t limited to operators, though. You can also overload functions by giving two or more functions the same name. The overloaded functions are distinguished by their parameter list. For example, a function that opens a file may have three different overloaded versions:

Quote:
int file_open(int descriptor); // #1

int file_open(const char *pathname); // #2

int file_open(const string & pathname); // #3
The compiler determines which of the three overloaded versions is to be called by examining the argument passed at the site of call:

Quote:
std::string file="modem.log";
file_open(file); // call file_open() #3
The overload resolution is static, meaning that the compiler determines at compile-time which of the three overloads should be called. Static overloading resolution has two advantages: The compiler is able to detect incorrect arguments, and there’s no performance overhead resulting from runtime resolution.

As opposed to certain popular programming languages, a C++ source file is compiled into native machine code, not bytecodes or any other form of intermediary code that needs to be translated further at runtime. The main advantages of this compilation to native code policy are efficiency and runtime speed. The compiled code is optimized for the target hardware. In addition, the implementation doesn’t waste precious CPU cycles and memory on translating bytecodes into machine code at runtime. There is tradeoff though. The compiled binaries aren’t portable to other platforms; instead, you need to compile the source file for every target platform, using a different compiler.
__________________
Reply With Quote
  #5 (permalink)  
Old 25-10-2008, 12:45 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Support for Object-Oriented Programming

C++ didn’t invent object-oriented programming. The first object-oriented programming language is Simula 67 which was created by Kristen Nygaard. However, C++ was the first widely used programming language that supported object-oriented programming. An object-oriented programming language typically supports these features:

Abstract datatyping
Information hiding
Encapsulation
Dynamic binding
Polymorphism
Inheritance
__________________
Reply With Quote
  #6 (permalink)  
Old 25-10-2008, 12:46 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Generic Programming

C++ also supports generic programming. Generic programming enables programmers to write algorithms and classes that are type-independent. The programmer writes a single code mold called a template, from which the compiler synthesizes type-specific specializations, or instances. Here’s an example of a generic swap algorithm:

Quote:
template <typename T> void swap( T & t1, T & t2)
{
T temp=t1;
t1=t2;
t2=temp;
}
int n=5, m=10;
string s1="hello", s2="HELLO";
swap(n,m);
swap(s1,s2);
The compiler treats the template function above as a mold from which it generates two specializations of swap(): one for type int and another instance for strings. To create these specializations, the compiler replaces the template parameter T with the concrete types int and string, respectively. This is similar to the way macros work except that in the case of templates the compiler, not the preprocessor, generates the code. As opposed to the preprocessor, the compiler can detect type mismatches and other violations of syntax rules. The Standard Library already has a swap() algorithm as well as dozens of other useful generic algorithms that count, sort, merge, replace, splice, copy, transform etc.

In addition to function templates, C++ supports class templates. A class template serves as a mold from which other classes are instantiated. Class templates are widely used in the Standard Library as generic containers: list, vector, stack, and so on. A rich set of generic algorithms that operate on generic containers is one of the main strengths of C++.
__________________
Reply With Quote
  #7 (permalink)  
Old 25-10-2008, 12:47 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Articles, Interviews, and Books

"A Tour of C++" is a sample chapter from The C++ Programming Language, Special Edition by Bjarne Stroustrup. This article is an excellent introduction to C++, its standard library, and the various programming paradigms it supports.

A History of C++: 1979- 1991 by Bjarne Stroustrup outlines the evolution of C++ during its first 12 years. The emphasis is on the ideas, constraints, and people that shaped the language, rather than the minutiae of language features. The evolution of C++ is traced from C with Classes to the early ANSI and ISO standards work and the explosion of use, interest, commercial activity, compilers, tools, environments, and libraries.

My recent interview with Bjarne Stroustrup discusses Stroustrup’s forthcoming book Programming: Principles and Practice using C++ as well as the future of C++, Stroustrup’s Danish roots.

Donald Knuth recently gave an interview that every professional programmer can’t afford to miss. In this interview, Knuth addresses the issue of Open Source code, multithreading and an urban legend about winning a programming contest with a single compilation.

The C++ Programming Language, Special Edition by Bjarne Stroustrup, is still the best C++ book you can find today. Although it’s 8 years old and therefore doesn’t cover the two last revision rounds of standard C++ (C++03 and C++09), it still offers a detailed and complete account of C++98.

C++ Standard Library Extensions, The: A Tutorial and Reference

By Pete Becker is the best (and only) complete reference to TR1 extensions. The book covers shared_ptr, the regex library, tuples, hash containers, reference_wrapper, the array and function class templates, type traits and the numeric libraries of C++.

Programming: Principles and Practice using C++ by Bjarne Stroustrup is targeted at beginners. Although this isn’t a book dedicated solely to C++, it uses C++ as the primary programming language. This book is particularly useful for novices who are learning C++ without any prior experience in programming.
__________________
Reply With Quote
  #8 (permalink)  
Old 25-10-2008, 12:48 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Special Member Functions: Constructors, Destructors, and the Assignment Operator

Objects are the fundamental unit of abstraction in object-oriented programming. In a broad sense, an object is a region of memory storage. Class objects have properties that are determined when the object is created. Conceptually, every class object has four special member functions: default constructor, copy constructor, assignment operator, and destructor. If these members are not explicitly declared by the programmer, the implementation implicitly declares them. This section surveys the semantics of the special member functions and their roles in class design and implementation.
__________________
Reply With Quote
  #9 (permalink)  
Old 25-10-2008, 12:52 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Constructors

A constructor initializes an object. A default constructor is one that can be invoked without any arguments. If there is no user-declared constructor for a class, and if the class doesn't contain const or reference data members, C++ implicitly declares a default constructor for it. Such an implicitly declared default constructor performs the initialization operations needed to create an object of this type. Note, however, that these operations don't involve initialization of user-declared data members. For example:

Quote:
class C
{
private:
int n;
char *p;
public:
virtual ~C() {}
};

void f()
{
C obj; // 1 implicitly-defined constructor is invoked
}
C++ synthesized a constructor for class C because it contains a virtual member function. Upon construction, C++ initializes a hidden data member called the virtual pointer, which every polymorphic class has. This pointer holds the address of a dispatch table that contains all the virtual member functions' addresses for that class. The synthesized constructor doesn't initialize the data members n and p, nor does it allocate memory for the data pointed to by the latter. These data members have an indeterminate value once obj has been constructed. This is because the synthesized default constructor performs only the initialization operations that are required by the implementation—not the programmer—to construct an object.

Other implementation-required operations that are performed by implicitly-defined constructors are the invocation of a base class constructor and the invocation of embedded object's constructor. However, C++ doesn't declare a constructor for a class if the programmer has defined one. For example:

Quote:
class C
{
private:
int n;
char *p;
public:
C() : n(0), p(0) {}
virtual ~C() {}
};
C obj; // 1 user-defined constructor is invoked
Now the data members of the object obj are initialized because the user-defined constructor was invoked to create it. This still leaves us with a mystery: The user-defined constructor only initializes the data members n and p. When did the initialization of the virtual pointer take place? Here's the answer: The compiler augments the user-defined constructor with additional code, which is inserted into the constructor's body before any user-written code, and performs the necessary initialization of the virtual pointer.

Trivial Constructors
As noted previously, compilers synthesize a default constructor for every class or struct, unless a constructor was already defined by the user. However, in certain conditions, such a synthesized constructor is redundant:

Quote:
class Empty {};
struct Person
{
char name[20];
double salary;
int age;
};
int main()
{
Empty e;
Person p;
p.age = 30; // public access allowed, no constructor needed
return 0;
}
C++ can instantiate Empty and Person objects without a constructor. In such cases, the implicitly declared constructor is said to be trivial. The fact that a constructor is considered trivial means that neither the programmer nor the compiler generates code for it. We'll discuss this in greater detail shortly.

Constructors of Built-in Types
You might be surprised to hear this: Built-in types such as char, int, and float also have constructors. You can initialize a variable by explicitly invoking its default constructor:

Quote:
char c = char();
int n = int ();
return 0;
This expression:

Quote:
char c = char();
is equivalent to this one:

Quote:
char c = char(0);
Of course, it's possible to initialize a fundamental type with values other than 0:

Quote:
float f = float (0.333);
char c = char ('a');
int *pi= new int (10);
float *pf = new float (0.333);
Note that this form is just "syntactic sugar." It's interchangeable with the more widely used form:

Quote:
char c = 'a';
float f = 0.333;
Explicit Constructors
Constructors have many peculiar characteristics. They don't have a name (and therefore can't be called directly, as opposed to ordinary member functions); they don't have a return value; and their address cannot be taken. Non-default constructors are even more odd. A constructor that takes a single argument operates as an implicit conversion operator by default. Today, I will explore this phenomenon in further detail and explain how to use the explicit qualifier to restrain constructors' behavior.

Constructor Categories

In essence, constructors are what differentiates between a POD struct and a real object, as they automatically shape a raw chunk of memory into an object with a determinate state. A class may have several constructors (in this discussion, I'm referring to "plain constructors," not to copy constructors), each of which taking a different number of arguments. A constructor that may be called without any arguments is a default-constructor.

A non-default constructor is one that takes one or more arguments. (The C++ literature provides no special name for this type of constructor, so I'm referring to it as a "non-default constructor.") Non-default constructors are further divided into two subcategories: those that take a single argument and thus operate as implicit conversion operators, and those that take multiple arguments. For example,

Quote:
class Date
{
public:
Date(); // default ctor; no arguments required
//non-default ctors:
Date(time_t t); // extracts date from a time_t value
Date(int d, int m, int y); //
};
The class Date has three constructors. The first one is a default constructor. The second one, which takes a single argument, operates as an implicit time_t to D conversion operator. As such, it will be invoked automatically in a context that requires a long to Date conversion (Remember that time_t is a synonym for long or a similar integral type). For example,

Quote:
Date d=std::time(0);// invokes ctor # 2 to create d
You're probably wondering how it works. Under the hood, the compiler transforms this code into something like this:

Quote:
//pseudo C++ code
time_t __value;
__value = std::time(0);
Date __temp(__value);//create a temporary Date object
Date d = __temp;
temp.C::~C(); //destroy temp
In this example, the automatic conversion is intentional and useful. Yet, there are many cases in which an implicit conversion is undesirable, for example:

Quote:
Date p=NULL; //actually meant 'Date *p=NULL'; compiles OK
Can you see what's happening here? NULL is defines as 0 or 0L in C++. The compiler silently transformed the code above into:

Quote:
//pseudo C++ code
Date temp(0L);//create a temporary Date object
Date d = temp; //assigned using operator =
temp.C::~C(); //destroy temp
The explicit Keyword

The problem here is that the implicit conversion (taking place behind the programmer's back) switches off the compiler's static type checking. Without this implicit conversion, the compiler would have complained about a type mismatch. C++ creators perceived this problem long ago. They decided to add a "patch" to the language in the form of the keyword explicit. Constructors declared explicit will refuse to perform such implicit conversions:

Quote:
class Date
{
//...
explicit Date(time_t t); // no implicit conversions
};
Now, the previous examples will not compile:

Date d =std::time(0); //error, can't convert 'long' to 'Date'
Date p=NULL; //also an error
To convert a time_t or any other integral value to a Date object, you need to use an explicit conversion now:

Quote:
Date d(std::time(0)); //OK
Date d2= Date(std::time(0)); //same meaning as above
Advice
If you examine a code corpus, say the Standard Library, you will see that most of the constructors taking one argument are explicit. One therefore could argue that this should have been the default behavior of constructors, whereas constructors that permit implicit conversions should have been the exception. Put differently, instead of explicit, C++ creators should have introduced the keyword implicit and changed the semantics of constructors so that they didn't function as implicit conversion operators.

However, this approach would have caused existing code to break. In some classes, for example std::complex and other mathematical classes, implicit conversions are rather useful. The C++ creators therefore decided to leave the original semantics constructors intact, while introducing a mechanism for disabling implicit conversions, when necessary.

As a rule, every constructor that takes a single argument, including constructors that take multiple arguments with default values such as the following, should be explicit, unless you have a good reason to allow implicit conversions:

Quote:
class File
{
public:
//this ctor may be called with a single argument
//it's therefore declared explicit:
explicit File(const char *name,
ios_base::openmode mode=ios_base::out,
long protection = 0666);
};
Member Initialization Lists
A constructor may include a member initialization (mem-initialization for short) list that initializes the object's data members. For example:

Quote:
class Cellphone //1: initialization by mem-init
{
private:
long number;
bool on;
public:
Cellphone (long n, bool ison) : number(n), on(ison) {}
};
The constructor of Cellphone can also be written as follows:

Cellphone (long n, bool ison) //2: initialization within ctor's body
{
number = n;
on = ison;
}
There is no substantial difference between the two forms in this case because the compiler scans the mem-initialization list and inserts its code into the constructor's body before any user-written code. Thus, the constructor in the first example is expanded by the compiler into the constructor in the second example. Nonetheless, the choice between using a mem-initialization list and initialization inside the constructor's body is significant in the following four cases:

Initialization of const members. For example:

Quote:
class Allocator
{
private:
const int chunk_size;
public:
Allocator(int size) : chunk_size(size) {}
};
Initialization of reference members. For example:

Quote:
class Phone;
class Modem
{
private:
Phone & line;
public:
Modem(Phone & ln) : line(ln) {}
};
Passing arguments to a constructor of a base class or an embedded object. For example:

Quote:
class base
{
//...
public:
//no default ctor
base(int n1, char * t) {num1 = n1; text = t; }
};
class derived : public base
{
private:
char *buf;
public:
//pass arguments to base constructor
derived (int n, char * t) : base(n, t) { buf = (new char[100]);}
};
Initialization of member objects. For example:

Quote:
#include<string>
using std::string;
class Website
{
private:
string URL
unsigned int IP
public:
Website()
{
URL = "";
IP = 0;
}
};
In the first three cases, a mem-initialization list is mandatory because these initializations must be completed before the constructor's execution. Conceptually, initializations listed in a member-initialization list take place before the constructor executes. In the fourth case, the use of a mem-init list is optional. However, it can improve performance in certain cases because it eliminates unnecessary creation and subsequent destruction of objects that would occur if the initialization were performed inside the constrictor's body.

Due to the performance difference between the two forms of initializing embedded objects, some programmers use mem-initialization exclusively. Note, however, that the order of the initialization list has to match the order of declarations within the class. This is because the compiler transforms the list so that it coincides with the order of the declaration of the class members, regardless of the order specified by the programmer. For example:

Quote:
class Website
{
private:
string URL; //1
unsigned int IP; //2
public:
Website() : IP(0), URL("") {} // initialized in reverse order
};
In the mem-initialization list, the programmer first initializes the member IP and then URL, even though IP is declared after URL. The compiler transforms the initialization list to the order of the member declarations within the class. In this case, the reverse order is harmless. When there are dependencies in the order of initialization list, however, this transformation can cause surprises. For example:

Quote:
class Mystring
{
private:
char *buff;
int capacity;
public:
explicit Mystring(int size) :
capacity(size), buff (new char [capacity]) {} undefined behavior
};
The mem-initialization list in the constructor of Mystring doesn't follow the order of declaration of Mystring's members. Consequently, the compiler transforms the list like this:

Quote:
explicit Mystring(int size) :
buff (new char [capacity]), capacity(size) {}
The member capacity specifies the number of bytes that new has to allocate, but it hasn't been initialized. The results in this case are undefined. There are two ways to avert this pitfall: Change the order of member declarations so that capacity is declared before buff, or move the initialization of buff into the constructor's body.

Copy Constructor
A copy constructor initializes its object with another object. If there is no user-defined copy constructor for a class, C++ implicitly declares one. A copy constructor is said to be trivial if it's implicitly declared, if its class has no virtual member functions and no virtual base classes, and if its entire direct base classes and embedded objects have trivial copy constructors. The implicitly defined copy constructor performs a memberwise copy of its sub-objects, as in the following example:

Quote:
#include<string>
using std::string;
class Website //no user-defined copy constructor
{
private:
string URL;
unsigned int IP;
public:
Website() : IP(0), URL("") {}
};
int main ()
{
Website site1;
Website site2(site1); //invoke implicitly defined copy constructor
}
The programmer didn't declare a copy constructor for class Website. Because Website has an embedded object of type std::string, which happens to have a user-defined copy constructor, the implementation implicitly defines a copy constructor for class Website and uses it to copy-construct the object site2 from site1. The synthesized copy constructor first invokes the copy constructor of std::string, and then performs a bitwise copying of the data members of site1 into site2.

Novices are sometimes encouraged to define the four special member functions for every class they write. As can be seen in the case of the Website class, not only is this unnecessary, but it's even undesirable under some conditions. The synthesized copy constructor (and the assignment operator, described in the next section) already "do the right thing." They automatically invoke the constructors of base and member sub-objects, they initialize the virtual pointer (if one exists), and they perform a bitwise copying of fundamental types. In many cases, this is exactly the programmer's intention anyway. Furthermore, the synthesized constructor and copy constructor enable the implementation to create code that's more efficient than user-written code, because it can apply optimizations that aren't always possible otherwise.
__________________

Last edited by Style Mantra; 25-10-2008 at 12:55 PM..
Reply With Quote
  #10 (permalink)  
Old 25-10-2008, 12:54 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Constructors FAQ, Part I

Question: What is a default constructor?
Answer: Many programmers believe that a default constructor is a constructor that the compiler automatically generates when the user doesn’t define a constructor. This isn’t correct. A default constructor can be user-defined or compiler-generated; it’s a default constructor if and only if it can be invoked without any arguments. The following classes all have default constructors:

Quote:
struct A
{
int x;
A(): x(0) {}
};
struct B: A
{
//no user-defined ctor.
//the compiler implicitly declares a default constructor
};
class C
{
public:
explicit C(int n=0, int m=0); // may be invoked with no arguments
};
C c0, c2(9,0);
As class C demonstrates, the default constructor needn’t be declared with an empty parameter list; C’s constructor qualifies as a default constructor because it may be invoked with no arguments.

Question: When does the compiler implicitly declare a default constructor?
Answer: The compiler will implicitly declare a default constructor for any class that doesn’t declare any constructor explicitly, provided that the class in question doesn’t contain any reference or const data members. Notice that if the user declares a copy constructor, that constructor will preclude the compiler’s implicit declaration of a default constructor. Consider:

Quote:
class A
{
int x;
public:
void f();
};//no user declared constructors of any kind;
A a; //OK, using implicitly-declared default ctor
The compiler implicitly declares a default constructor, copy constructor (as well as an assignment operator and a destructor which I will not discuss here) for class A because the implementer of this class didn’t declare any constructor for it. Let’s examine this issue more closely. Suppose the user adds the following copy constructor declaration:

Quote:
class A2
{
int x;
public:
A2(const A2&); //the access type doesn’t matter, it could be private or protected too
void f();
};
The compiler doesn’t declare an implicit default constructor for class A2 because the user has already declared a constructor. Even if the user-declared constructor is a copy constructor or a constructor taking multiple arguments, that’s enough to preclude the implicit declaration of a default constructor! This means that A2 doesn’t have a default constructor at all:

Quote:
A2 a2; //error, A2 has no default constructor
As an aside, you can’t even use the copy-constructor to instantiate an object of type A2 because you can’t instantiate the argument for the copy constructor:

Quote:
A2 a3(a2); //a2 cannot be instantiated because no default ctor is available
Question: What does the implicitly declared default constructor do?
Answer: Here’s another common myth -- many believe that the implicitly-declared default constructor does secret initialization operations behind their back, or that it allocates memory for the object. This is sheer nonsense. The implicitly-declared constructor does absolutely nothing! Remember: declaring a constructor -- either explicitly or implicitly -- doesn’t necessarily mean that the constructor is also defined. The following examples demonstrate the difference between a constructor declaration and its definition:

Quote:
class B
{
B(); //declaration only
};
B::B() {} //separate definition of the user-declared default constructor

class C
{
C() {} //declaration and definition
};
class D
{
//implicit declaration of a default constructor, no implicit definition
};
class E
{
//implicit declaration + implicit definition of a default constructor
virtual void f();
};
class F
{
virtual void f();
public:
F(); ////explicit declaration a default constructor, user forgot a definition
};
In the last example, the lack of a definition for F’s default constructor is most likely a programmer’s omission. This type of a human error will cause a linkage error when you try to instantiate this class:

Quote:
F f; //linkage error: symbol ’F::F()’ could not be resolved
To conclude, a user-declared constructor is never implicitly-defined. If the user has declared a constructor, he or she is responsible for defining it as well, unless they intentionally left it unimplemented (to prevent object copying for instance). By contrast, an implicitly-declared constructor may be implicitly-defined under certain conditions which I will explain in the second part of this series.

The second part of this series will also answer additional questions including: When does the compiler implicitly define a default constructor? Is it true that the implicitly-defined constructor allocate memory for its object? Does the implicitly-defined constructor initialize the object’s data members?
__________________
Reply With Quote
  #11 (permalink)  
Old 25-10-2008, 12:57 PM
Style Mantra's Avatar
R.I.P
 

Join Date: Feb 2006
Posts: 17,047
Country: Users Flag!
Images: 50
Thanks: 29
Thanked 23 Times in 22 Posts
Rep Power: 20
Style Mantra has a spectacular aura aboutStyle Mantra has a spectacular aura about
Re: Learn C++

Constructors FAQ, Part II

The second installment lists the conditions under which an implicitly-declared constructor will also be implicitly-defined. It also explains why the compiler implicitly declares constructors even when they are not defined, seemingly for no purpose.

Question: When Does the Compiler Implicitly-Define An Implicitly-Declared Constructor?
Answer: An implicitly-declared default constructor is implicitly-defined if and only if the implementation needs that definition. The implementation needs an implicit definition in the following cases:

Classes with virtual member functions. A class that has virtual member functions must have a non-trivial constructor. A non-trivial constructor is either a user-defined constructor or a constructor that is implicitly defined. The non-trivial constructor is responsible for internal initializations such as assigning the correct vptr address of each polymorphic object.

Base and embedded subobjects. A class must have a non-trivial constructor if it has base class(es) with non-trivial constructor(s) or embedded objects with non-trivial constructor(s). The non-trivial constructor has to initialize the base class(es) and the embedded object(s) first. For example:

Quote:
struct T
{
T() {cout<<"hello"<<endl;} //user-defined constructor
};
struct U:T
{
//default ctor implicitly defined
};
The compiler implicitly-defines a default constructor for U. U’s constructor invokes the non-trivial constructor of the base class T whenever you instantiate an object of type U:

Quote:
U u; //implicitly defined ctor invokes T::T() first.
Virtual inheritance. The presence of a virtual base class necessitates a non-trivial constructor to ensure that only one virtual subobject is present in every derived object. Therefore, if a class has any virtual base class(es), its constructor must be non-trivial.

Question: Why Does The Compiler Implicitly Declare Trivial Constructors If They Are Never Defined?
Answer: Under certain conditions, the compiler implicitly-declares a default constructor but doesn’t define it. Such a constructor is said to be trivial. Many C++ programmers find this notion of trivial member functions rather confusing. Why on earth does the compiler bother to declare a member function implicitly when it knows that that function won’t be implicitly defined? Do implicit declarations of this kind serve any purpose?

The first thing to bear in mind is that implicit declarations (and implicit definitions) are conceptual. That is, the compiler doesn’t go through your header files and inserts lines of code with constructor declarations to them. Rather, the compiler, the linker and the program behave as if the trivial member functions were declared. In practice, the compiler simply sets a few bits in a class’ type information record, indicating that the said type has a (trivial) default constructor declaration. So if you’re worried about excess verbiage of source files or the potential bloat of executable files, rest assured that nothing of this kind should happen.

Now let’s get to the more important conundrum: why bother at all with these trivial declarations? After all, C doesn’t need this mechanism for its structs and unions. The truth is that implicit declarations have a contractual role. Each implicit declaration is like an article in a contract that states how a certain class may be used. When the compiler implicitly declares one of the special member functions, it grants certain authorizations to the user. By contrast, if the compiler doesn’t implicitly-declare a member function, the user is restricted with respect the class’s usage. Consider:

Quote: