CPP

Ace your homework & exams now with Quizwiz!

Long && Short specifier

modify the maximum and minimum values that a data type will hold. A plain int must be at least the size of a short.

yo

moma

Operator Precedence 10

& Bitwise AND Left-to-right ----------------------------------------------------------------------------------------------------

Operator Precedence 13

&& Logical AND Left-to-right ----------------------------------------------------------------------------------------------------

Logical operators

( !, &&, || )

Bitwise operators

( &, |, ^, ~, <<, >> )

Arithmetic operators

( +, -, *, /, % )

Comma operator

( , )

Relational and comparison operators

( ==, !=, >, <, >=, <= )

Ternary operator

(condition) ? (if_true) : (if_false)

Bitwise operators

(only work with integral types) allow you to manipulate individual bits in a number. And, or, exclusive or, ones complement operator (bitwise not) (&) produces a one in the output bit if both input bits are one; otherwise it produces a zero (|) produces a one in the output bit if either input bit is a one and produces a zero only if both input bits are zero. (^) produces a one in the output bit if one or the other input bit is a one, but not both. (~) is a unary operator - it only takes one argument (all other bitwise operators are binary operators). Bitwise not produces the opposite of the input bit - a one if the input bit is zero, a zero if the input bit is one.

------------------------------------------------------------------------------------------------------ Operator Precedence 5

* Multiplication Left-to-right / Division % Modulo (remainder) ----------------------------------------------------------------------------------------------------

Operator Precedence 6

+ Addition Left-to-right - Subtraction ----------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------ Operator Precedence 2

++ Postfix increment Left-toRight -- Postfix decrement () Function call [] Array subscripting . Element selection by reference -> Element selection through pointer typeid() Run-time type information const_cast Type cast (C++ only) (see const_cast) dynamic_cast Type cast (C++ only) (see dynamic cast) reinterpret_cast Type cast (C++ only) (see reinterpret_cast) static_cast Type cast (C++ only) (see static_cast)

------------------------------------------------------------------------------------------------------ Operator Precedence 3

++ Prefix increment Right-to-left -- Prefix decrement + Unary plus - Unary minus ! Logical NOT ~ Bitwise NOT (One's Complement) (type) Type cast * Indirection (dereference) & Address-of sizeof Size-of new, new[] Dynamic memory allocation (C++ only) delete, delete[] Dynamic memory deallocation (C++ only)

member function

- a function declared in the scope of a class. A member function that is not a static member function must be called for an object of its class. TC++PL 10.2.1, D&E 2.3, 3.5.

pure virtual function

- virtual function that must be overridden in a derived class. Indicated by the curious =0 syntax. A pure virtual function can be defined in the class where it is declared pure, but needn't be and usually isn't. A class with at least one pure virtual function is an abstract class.

------------------------------------------------------------------------------------------------------ Operator Precedence 4

.* Pointer to member (C++ only) Left-to-right ->* Pointer to member (C++ only)

Body

A body is a collection of statements enclosed in braces. I.e a function body

Qualifiers vs Keywords vs Identifiers

A qualifier: adds an extra "quality", such as specifying volatility or constness of a variable. They're similar to adjectives: "a fickle man", "a volatile int", "an incorruptible lady", "a const double". With or without a qualifier, the variable itself still occupies the same amount of memory, and each bit has the same interpretation or contribution to the state/value. Qualifiers just specify something about how it may be accessed or where it is stored.

// An amazing dictionary of terms http://www.stroustrup.com/glossary.html Integral Types

An integral type is one which has only integers - whole numbers. The purpose of floating point types is to represent non-integers as well. Float is not an integral type.

lvalue vs rvalue: rvalue

An rvalue is any expression that has a value, but cannot have a value assigned to it. One could also say that an rvalue is any expression that is not an lvalue . An example of an rvalue would be a literal constant - something like '8′, or '3.14′. So, clearly the value '8′ in the code above is an rvalue.

Assignment operator

Assignment is performed with the operator =. It means "Take the right-hand side (often called the rvalue) and copy it into the left-hand side (often called the lvalue)."

Casting: Upcasting && Downcasting: Upcasting

C++ allows that a derived class pointer (or reference) to be treated as base class pointer. This is upcasting.

Definition vs Declaration

Declaration: "Somewhere, there exists a foo." introduces an identifier and describes its type, be it a type, object, or function. It introduces names into a translation unit or re-declares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names. Definition: "...and here it is!" actually instantiates/implements this identifier. It's what the linker needs in order to link references to those entities. A definition says: "Make this variable here" or "Make this function here." It allocates storage for the name. This meaning works whether you're talking about a variable or a function; in either case, at the point of definition the compiler allocates storage. For a variable, the compiler determines how big that variable is and causes space to be generated in memory to hold the data for that variable. For a function, the compiler generates code, which ends up occupying storage in memory.

Namespace

Each set of C++ definitions in a library or program is "wrapped" in a namespace, and if some other definition has an identical name, but is in a different namespace, then there is no collision. If you simply include a header file and use some functions or objects from that header without using a namespace you'll get an error. You included the header file but all the declarations are within a namespace and you didn't tell the compiler that you wanted to use the declarations in that namespace. If you want to use the declarations and/or definitions in a namespace use using. using namespace std;

Void pointer: void*

If you state that a pointer is a void*, it means that any type of address at all can be assigned to that pointer (whereas if you have an int*, you can assign only the address of an int variable to that pointer). int main() { void* vp; char c; int i; float f; double d; // The address of ANY type can be // assigned to a void pointer: vp = &c; vp = &i; vp = &f; vp = &d; } ///:~ Once you assign to a void* you lose any information about what type it is. This means that before you can use the pointer, you must cast it to the correct type: int main() { int i = 99; void* vp = &i; // Can't dereference a void pointer: // *vp = 3; // Compile-time error // Must cast back to int before dereferencing: *((int*)vp) = 3; // Dereference the cast. The cast (int*)vp takes the void* and tells the compiler to //treat it as an int*, and thus it can be successfully dereferenced } ///:~ //side note, You cannot have a void reference

Literal

In computer science, a literal is a notation for representing a fixed value in source code Translation Unit::: A translation unit is the basic unit of compilation in C++. It consists of the contents of a single source file, plus the contents of any header files directly or indirectly included by it, minus those lines that were ignored using conditional preprocessing statements.A single translation unit can be compiled into an object file, library, or executable program. The notion of a translation unit is most often mentioned in the contexts of the One Definition Rule, and templates.

Late Binding

In some programs, it is not possible to know which function will be called until runtime (when the program is run). This is known as late binding (or dynamic binding). I.e using function pointers int add(int x, int y){ return x + y;} int subtract(int x, int y){ return x - y;} int multiply(int x, int y){ return x * y;} int (*pFcn)(int, int) = nullptr; switch (op){ case 0: pFcn = add; break; case 1: pFcn = subtract; break; case 2: pFcn = multiply; break;} std::cout << "The answer is: " << pFcn(x, y) << std::endl;

Scope / Scoping

Scoping rules tell you where a variable is valid, where it is created, and where it gets destroyed (i.e., goes out of scope). The scope of a variable extends from the point where it is defined to the first closing brace that matches the closest opening brace before the variable was defined. That is, a scope is defined by its "nearest" set of braces.

#define

TABLE_SIZE 100 int table1[TABLE_SIZE]; After the preprocessor has replaced TABLE_SIZE, the code becomes equivalent to: int table1[100]; #define can work also with parameters to define function macros: #define getmax(a,b) a>b?a:b You would use this in code as follows y= getmax(x,2); Defined macros are not affected by block structure. A macro lasts until it is undefined with the #undef preprocessor directive: #define TABLE_SIZE 100 int table1[TABLE_SIZE]; #undef TABLE_SIZE #define TABLE_SIZE 200 int table2[TABLE_SIZE]; This would generate int table1[100]; int table2[200];

Mathematical operators

The basic mathematical operators are the same as the ones available in most programming languages: addition (+), subtraction (-), division (/), multiplication (*), and modulus (%; this produces the remainder from integer division).

Abstract or user defined data type

These data types are defined by user itself. Like, defining a class in C++ or a structure.

Const cast

This one is primarily used to add or remove the const modifier of a variable. const int myConst = 5; int *nonConst = const_cast<int*>(&myConst); // removes const Although const cast allows the value of a constant to be changed, doing so is still invalid code that may cause a run-time error. This could occur for example if the constant was located in a section of read-only memory. *nonConst = 10; // potential run-time error Const cast is instead used mainly when there is a function that takes a non-constant pointer argument, even though it does not modify the pointee. void print(int *p) { std::cout << *p; } The function can then be passed a constant variable by using a const cast. print(&myConst); // error: cannot convert // const int* to int* print(nonConst); // allowed

Preprocessor macros (also a mathematical operator)

To define preprocessor macros we can use #define. Its syntax is: #define identifier replacement When the preprocessor encounters this directive, it replaces any occurrence of identifier in the rest of the code by replacement. This replacement can be an expression, a statement, a block or simply anything. The preprocessor does not understand C++ proper, it simply replaces any occurrence of identifier by replacement.

(<<) produces the operand to the left of the operator shifted to the left by the number of bits specified after the operator. (>>) produces the operand to the left of the operator shifted to the right by the number of bits specified after the operator. If the value after the shift operator is greater than the number of bits in the left-hand operand: the result is undefined. If the left-hand operand is unsigned: the right shift is a logical shift so the upper bits will be filled with zeros. If the left-hand operand is signed: the right shift may or may not be a logical shift (that is, the behavior is undefined). Unary operators

Unary operators act on only one operand in an expression. Indirection operator (*) Address-of operator (&) Unary plus operator (+) Unary negation operator (-) Logical negation operator (!) One's complement operator (~) Prefix increment operator (++) Prefix decrement operator (--) Cast operator () sizeof operator __uuidof operator __alignof operator new operator delete operator

Operand

the quantity on which an operation is to be done.

Virtual

You state that you want a function to have the flexibility of late-binding properties using the keyword virtual. virtual member function - a member function that a derived class can override; the primary mechanism for run-time polymorphism in C++. A virtual member function is sometimes called a method.

Explicit type casting operator

const_cast<new_type>(expression)

Code reading p_2

float (*(*fp2)(int,int,float))(int); says "fp2 is a pointer to a function that takes three arguments (int, int, and float) and returns a pointer to a function that takes an integer argument and returns a float." If you are creating a lot of complicated definitions, you might want to use a typedef.

Data type Modifiers

i.e signed, unsigned, short, long

Comma Operator

separating variable names in multiple definitions: int i, j, k; function argument lists Comma operator nuance: The comma operator has the lowest precedence of all C/C++ operators. Therefore it's always the last one to bind to an expression, meaning this: a = b, c; is equivalent to: (a = b), c; Another interesting fact is that the comma operator introduces a sequence point. This means that the expression: a+b, c(), d is guaranteed to have its three subexpressions (a+b, c() and d) evaluated in order. This is significant if they have side-effects. Normally compilers are allowed to evaluate subexpressions in whatever order they find fit; for example, in a function call: someFunc(arg1, arg2, arg3) arguments can be evaluated in an arbitrary order. Note that the commas in the function call are not operators; they are separators.

Code reading p_1

void * (*(*fp1)(int))[10]; says "fp1 is a pointer to a function that takes an integer argument and returns a pointer to an array of 10 void pointers."

------------------------------------------------------------------------------------------------------- Complicated declarations & definitions

void * (*(*fp1)(int))[10]; float (*(*fp2)(int,int,float))(int); typedef double (*(*(*fp3)())[10])(); int (*(*f4())[10])();

Operator Precedence 12

| Bitwise OR (inclusive or) Left-to-right ----------------------------------------------------------------------------------------------------

Operator Precedence 14

|| Logical OR Left-to-right ----------------------------------------------------------------------------------------------------

Local Variables

Variables that are declared inside a function or a block are called local variables and are said to have local scope. These local variables can only be used within the function or block in which these are declared.

Handle Calsses: TODO sequence point

(point of execution) defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.They are often mentioned in reference to C and C++, because they are a core concept for determining the validity and, if valid, the possible results of expressions.

Global scope

"::" It means global scope. You might need to use this operator when you have conflicting functions or variables in the same scope and you need to use a global one. You might have something like void bar(); // this is a global function class foo { void some_func() { ::bar(); } // this function is calling the global bar() and not the class version void bar(); // this is a class member };

Preprocessor const

#define PI 3.14159 Everywhere you used PI, the value 3.14159 is substituted by the preprocessor. you place control of these constants outside the scope of the compiler. No type checking is performed on the name PI and you can't take the address of PI (so you can't pass a pointer or a reference to PI). PI cannot be a variable of a user-defined type. The meaning of PI lasts from the point it is defined to the end of the file; the preprocessor doesn't recognize scoping.

Pointers

&: will can be used to access the location in memory. *: the operator that defines a pointer int a = 47; I.e: int* ip; // ip points to an int variable, but it doesn't need the address yet // we can give it it's address later Since a general guideline for C++ programming is that you should always initialize a variable at the point of definition, this form actually works better. I.e: int* ipa = &a; To access a variable through a pointer, you dereference a pointer using the same operator that you used to define it, like this: I.e *ipa = 100; Now a contains the value 100 instead of 47.

Conditional ternary operator

( ? )

Conditional inclusions

(#ifdef, #ifndef, #if, #endif, #else and #elif) #ifdef ::: allows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter which its value is. For example: 1 2 3 #ifdef TABLE_SIZE int table[TABLE_SIZE]; #endif In this case, the line of code int table[TABLE_SIZE]; is only compiled if TABLE_SIZE was previously defined with #define, independently of its value. If it was not defined, that line will not be included in the program compilation.

Logical operators

(&&), (||): produce a true or false based on the logical relationship of its arguments. Remember that in C and C++, a statement is true if it has a non-zero value, and false if it has a value of zero. If you print a bool, you'll typically see a '1' for true and '0' for false.

Increment and decrement operators

(++, --)

Assignment operator

(=)

access block

(a group of declarations delimited by access specifiers)

Operator Precedence 17

, Comma Left-to-right ----------------------------------------------------------------------------------------------------

Early Binding

- Early binding (also called static binding) means the compiler (or linker) is able to directly associate the identifier name (such as a function or variable name) with a machine address. Direct Function calls can be resolved this way. i.e void printValue(int value){ std::cout << value;} int main(){ printValue(5); // This is a direct function call}

const in passing parameters

//Parameter by value void Subroutine1(int Parameter1) { printf("%d",Parameter1);} The subroutine can read the value of the variable passed to it but not alter it because any alterations it makes are only made to the copy and are lost when the subroutine ends. //Parameter by reference void Subroutine3(int &Parameter1) { Parameter1=96;} An '&' to the parameter name causes the actual variable itself, rather than a copy, to be used as the parameter in the subroutine. In this case we sent Parameter with it's address in memory as a 'reference' and actually changed the value in memory so that the value of parameter is also changed to 96 in the calling function. // const reference parameter void Subroutine4(big_structure_type const &Parameter1); This passes the value by reference and doesn't allow you to alter it. If you passed by value you also wouldn't be able to modify Pramaeter1 in the calling function, However, the advantage here is that a reference is less expensive to execute than copying. // const that prevents modification of object member variables class Class2 { void Method1() const; int MemberVariable1;} The const after Method1() will ban Method1 in Class2 from being anything which can attempt to alter any member variables in the object.

How would you implement polmorphism, write an example ?

0. Use virtual functions to dynamically call a function at runtime 1) A base class and a derived class. 2) A function with same name in base class and derived class. 3) A pointer or reference of base class type pointing or referring to an object of derived class. #include<iostream> using namespace std; class Base { public: virtual void show() { cout<<" In Base \n"; } }; class Derived: public Base { public: void show() { cout<<"In Derived \n"; } }; int main(void) { Base *bp = new Derived; bp->show(); // RUN-TIME POLYMORPHISM return 0; }

What is this pointer?

0. is a constant pointer that holds the memory address of the current object. 1. passed as a hidden argument to all nonstatic member function calls 2. available as a local variable within the body of all nonstatic functions

What is a friend class and function ?

1. A friend class can access private and protected members of other class 2. friend function can be given special grant to access private and protected members.

Whats the difference between references and pointers ?

1. Created reference cannot be made to reference other object. 2. References cannot be NULL. 3. A reference must be initialized when declared

What is an inline function ?

1. Inline function is a function that is expanded in line when it is called. 2. This substitution is performed by the C++ compiler at compile time. 3. Inline function may increase efficiency if it is small. //The syntax for defining the function inline is: inline return-type function-name(parameters) { // function code } Compiler can ignore the request for inlining.

What does cpp have that C doesn't

1. The references are different 2. OOP e.g function overloading, templates ... 3. Suports exeption handling at language level

What are virtual functions ? give an example

1. virtual functions are determined at runtime 2. used for polymorphism 3. used with inheritance

What are VTABLE and VPTR?

1. vtable is a table of function pointers. It is maintained per class. 2. vptr is a pointer to vtable. It is maintained per object. Compiler adds additional code at two places to maintain and use vtable and vptr. 1) Code in every constructor. This code sets vptr of the object being created. This code sets vptr to point to vtable of the class. 2) Code with polymorphic function call (e.g. bp->show() in above code). Wherever a polymorphic call is made, compiler inserts code to first look for vptr using base class pointer or reference (In the above example, since pointed or referred object is of derived type, vptr of derived class is accessed). Once vptr is fetched, vtable of derived class can be accessed. Using vtable, address of derived derived class function show() is accessed and called.

Sizeof ------------------------------------------------------------------------------------------------- Precedence of operators: Operator Description Orientation ------------------------------------------------------------------------------------------------- Operator Precedence 1

:: scope qualifier NONE

Operator Precedence 8

< Less than Left-to-right <= Less than or equal to > Greater than >= Greater than or equal to ----------------------------------------------------------------------------------------------------

Operator Precedence 7

<< Bitwise left shift Left-to-right >> Bitwise right shift ----------------------------------------------------------------------------------------------------

Operator Precedence 16

= Direct assignment Right-to-left += Assignment by sum -= Assignment by difference *= Assignment by product /= Assignment by quotient %= Assignment by remainder <<= Assignment by bitwise left shift >>= Assignment by bitwise right shift &= Assignment by bitwise AND ^= Assignment by bitwise XOR |= Assignment by bitwise OR ----------------------------------------------------------------------------------------------------

Operator Precedence 9

== Equal to Left-to-right != Not equal to ----------------------------------------------------------------------------------------------------

Operator Precedence 15

?: Ternary conditional (see ?:) Right-to-left ----------------------------------------------------------------------------------------------------

Const

A const in C++ defaults to internal linkage; that is, it is visible only within the file where it is defined and cannot be seen at link time by other translation units. You must always assign a value to a const when you define it, except when you make an explicit declaration using extern: Because the compiler cannot always avoid allocating storage for a const, const definitions must default to internal linkage, that is, linkage only within that particular translation unit. Otherwise, linker errors would occur with complicated consts because they cause storage to be allocated in multiple cpp files. The linker would then see the same definition in multiple object files, and complain. Because a const defaults to internal linkage, the linker doesn't try to link those definitions across translation units, and there are no collisions. With built-in types, which are used in the majority of cases involving constant expressions, the compiler can always perform constant folding.

What is a copy constructor ?

A copy constructor is a member function which initializes an object using another object of the same class.

C vs C++ Struct (with/without typdef)

A struct is a way to collect a group of variables into a structure. Once you create a struct, then you can make many instances of this "new" type of variable you've invented. struct Structure1 { char c;int i;}; int main() { struct Structure1 s1, s2; s1.c = 'a'; s2.i = 1;} ///:~ The struct declaration must end with a semicolon. One thing you'll notice is the awkwardness of the use of Structure1 (as it turns out, this is only required by C, not C++). In C, you can't just say Structure1 when you're defining variables, you must say struct Structure1. This is where typedef becomes especially handy in C: (with typedef) typedef struct { char c;int i;}Structure1; int main() { Structure1 s1, s2; s1.c = 'a'; s2.i = 1;} ///:~ ( refering to the struct during its definition )

Internal variables vs external variable

A variable with internal linkage is called an internal variable (or static variable). Variables with internal linkage can be used anywhere within the file they are defined in, but can not be referenced outside the file they exist in. A variable with external linkage is called an external variable. (or extern) Variables with external linkage can be used both in the file they are defined in, as well as in other files.

What is an access specifier ?

Access specifiers are used to define how the members (functions and variables) can be accessed outside the class. Private: Members declared as private are accessible only within the same class and they cannot be accessed outside the class they are declared. Child classes are also not allowed to access private members of parent. Public: Members declared as public are accessible from anywhere. Protected: Only the class and its child classes can access protected members.

Encapsilation

All C++ programs are composed of the following two fundamental elements − In normal terms Encapsulation is defined as wrapping up of data and information under a single unit. In Object Oriented Programming, Encapsulation is defined as binding together the data and the functions that manipulates them. Program statements (code) − This is the part of a program that performs actions and they are called functions. Program data − The data is the information of the program which gets affected by the program functions. Encapsulation is an Object Oriented Programming concept that binds together the data and functions that manipulate the data, and that keeps both safe from outside interference and misuse. Data encapsulation led to the important OOP concept of data hiding.

Operator

An operator takes one or more arguments and produces a new value.

Access specifier does not matter for a friend class

C++ standard, section § 11.3 / 9 [friend.class] The meaning of the friend declaration is the same whether the friend declaration appears in the private, protected or public (9.2) portion of the class member-specification.

Const pointers

Basically 'const' applies to whatever is on its immediate left (other than if there is nothing there in which case it applies to whatever is its immediate right). const int * Constant2 declares that Constant2 is a variable pointer to a constant integer and int const * Constant2 is an alternative syntax which does the same, whereas int * const Constant3 declares that Constant3 is constant pointer to a variable integer and int const * const Constant4 declares that Constant4 is constant pointer to a constant integer.

Decorated names

Functions, data, and objects in C and C++ programs are represented internally by their decorated names. A decorated nameis an encoded string created by the compiler during compilation of an object, data, or function definition. It records calling conventions, types, function parameters and other information together with the name. This name decoration, also known as name mangling, helps the linker find the correct functions and objects when linking an executable.

Specifying storage allocation Global Variables

Global variables are unaffected by scopes and are always available (i.e., the lifetime of a global variable lasts until the program ends).

Combining variables with struct C vs C++ struct

In C++ struct and class are the exact same thing, except for that struct defaults to publicvisibility and class defaults to private visiblity. In C, struct names are in their own namespace, so if you have struct Foo {};, you need to write struct Foo foo; to create a variable of that type, while in C++ you can write just Foo foo;, albeit the C style is also permitted. C programmers usually use typedef struct {} Foo; to allow the C++ syntax for variable definitions. The C programming language also does not support visibility restrictions, member functions or inheritance.

Dynamic cast examples

In the example below, a MyChild pointer is converted into a MyBase pointer using a dynamic cast. This derived-to-base conversion succeeds, because the Child object includes a complete Base object. class MyBase { public: virtual void test() {} }; class MyChild : public MyBase {}; int main() { MyChild *child = new MyChild(); MyBase *base = dynamic_cast<MyBase*>(child);//ok } The next example attempts to convert a MyBase pointer to a MyChild pointer. Since the Base object does not contain a complete Child object this pointer conversion will fail. To indicate this, the dynamic cast returns a null pointer. This gives a convenient way to check whether or not a conversion has succeeded during run-time. The advantage of using a dynamic cast is that it allows the programmer to check whether or not a conversion has succeeded during run-time. The disadvantage is that there is a performance overhead associated with doing this check. For this reason using a static cast would have been preferable in the first example, because a derived-to-base conversion will never fail. MyBase *base = new MyBase(); MyChild *child = dynamic_cast<MyChild*>(base); if (child == 0) std::cout << "Null pointer returned"; If a reference is converted instead of a pointer, the dynamic cast will then fail by throwing a bad_cast exception. This needs to be handled using a try-catch statement. However, in the second example the conversion may either succeed or fail. It will fail if the MyBase object contains a MyBase instance and it will succeed if it contains a MyChild instance. In some situations this may not be known until run-time. When this is the case dynamic cast is a better choice than static cast. #include <exception> // ... try { MyChild &child = dynamic_cast<MyChild&>(*base); } catch(std::bad_cast &e) { std::cout << e.what(); // bad dynamic_cast } If the base-to-derived conversion had been performed using a static cast instead of a dynamic cast the conversion would not have failed. It would have returned a pointer that referred to an incomplete object. Dereferencing such a pointer can lead to run-time errors. // Allowed, but invalid MyChild *child = static_cast<MyChild*>(base); // Incomplete MyChild object dereferenced (*child);

The C assert( ) macro

In the standard header file <cassert> you'll find assert( ), which is a convenient debugging macro. When you use assert( ), you give it an argument that is an expression you are "asserting to be true." The preprocessor generates code that will test the assertion. If the assertion isn't true, the program will stop after issuing an error message telling you what the assertion was and that it failed. #include <cassert> // Contains the macro using namespace std; int main() { int i = 100; assert(i != 100); // Fails} ///:~

Regular cast vs. static_cast vs. dynamic_cast vs const_cast vs reinterpret_cast: Regular C style cast

MyClass *m = (MyClass *)ptr; C-style cast would allow an integer pointer to point to a char. char c = 10;// 1 byte int *p = (int*)&c; // 4 bytes Since this results in a 4-byte pointer ( a pointer to 4-byte datatype) pointing to 1 byte of allocated memory, writing to this pointer will either cause a run-time error or will overwrite some adjacent memory. *p = 5; // run-time error: stack corruption In contrast to the C-style cast, the static cast will allow the compiler to check that the pointer and pointee data types are compatible

Static cast

MyClass *m = static_cast<MyClass *>(ptr); static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. static_cast include typical castless conversions, narrowing (information-losing) conversions, forcing a conversion from a void*, implicit type conversions, and static navigation of class hierarchies. //: C03:static_cast.cpp void func(int) {} int main() { int i = 0x7fff; // Max pos value = 32767 long l; float f; // (1) Typical castless conversions: l = i; f = i; // Also works: l = static_cast<long>(i); f = static_cast<float>(i); // (2) Narrowing conversions: i = l; // May lose digits i = f; // May lose info // Says "I know," eliminates warnings: i = static_cast<int>(l); i = static_cast<int>(f); char c = static_cast<char>(i); // (3) Forcing a conversion from void* : void* vp = &i; // Old way produces a dangerous conversion: float* fp = (float*)vp; // The new way is equally dangerous: fp = static_cast<float*>(vp); // (4) Implicit type conversions, normally // performed by the compiler: double d = 0.0; int x = d; // Automatic type conversion x = static_cast<int>(d); // More explicit func(d); // Automatic type conversion func(static_cast<int>(d)); // More explicit } ///:~ MyClass *m = dynamic_cast<MyClass *>(ptr);

What are the major features of Cpp

Object: Encapsulation and Data abstraction: Wrapping up(combining) of data and functions into a single translation unit is known as encapsulation. Data abstraction - providing only needed information to the outside world. Inheritance: Inheritance is the process by which objects of one class acquire the properties of objects of another class. Polymorphism: Polymorphism means ability to take more than one form. Dynamic Binding: In dynamic binding, the code to be executed in response to function call is decided at runtime. Message Passing: Objects communicate with one another by sending and receiving information to each other. '

What is operation overloading ?

Operating overloading allows us to make operators to work for user defined classes. For example, we can overload an operator '+' in a class like String so that we can concatenate two strings by just using +.

C++ References: Pointers vs References

References int main() { int x = 47; cout << "x = " << x << endl; cout << "&x = " << &x << endl; f(x); // Looks like pass-by-value, // is actually pass by reference cout << "x = " << x << endl;} ///:~ void f(int& r) { cout << "r = " << r << endl; cout << "&r = " << &r << endl; r = 5; cout << "r = " << r << endl; } x = 47 &x = 0065FE00 r = 47 &r = 0065FE00 r = 5 x = 5 Pointers int main() { int x = 47; cout << "x = " << x << endl; cout << "&x = " << &x << endl; f(&x); cout << "x = " << x << endl; } ///:~ void f(int* p) { cout << "p = " << p << endl; cout << "*p = " << *p << endl; *p = 5; cout << "p = " << p << endl;} x = 47 &x = 0065FE00 p = 0065FE00 *p = 47 p = 0065FE00 x = 5

reinterpret_cast

The C++ standard guarantees the following: static_casting a pointer to and from void* preserves the address. That is, in the following, a, b and c all point to the same address: int* a = new int(); void* b = static_cast<void*>(a); int* c = static_cast<int*>(b); reinterpret_cast only guarantees that if you cast a pointer to a different type, and then reinterpret_cast it back to the original type, you get the original value. So in the following: int* a = new int(); void* b = reinterpret_cast<void*>(a); int* c = reinterpret_cast<int*>(b); a and c contain the same value, but the value of b is unspecified. (in practice it will typically contain the same address as a and c, but that's not specified in the standard, and it may not be true on machines with more complex memory systems.) For casting to and from void*, static_cast should be preferred. General knowledge - cast: If you take the address of a const object, you produce a pointer to a const, and this cannot be assigned to a nonconst pointer without a cast. The old-style cast will accomplish this, but the const_cast is the appropriate one to use. The same holds true for volatile.

Delete

The delete keyword is the complement of new, and must be applied to release any storage that is allocated with new (if you forget to use delete, that storage remains unavailable, and if this so-called memory leak happens enough, you'll run out of memory) (delete an array) delete []myArray;

this:The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct , or union type. It points to the object for which the member function is called. Static member functions do not have a this pointer. Access specifier

There are 3 access specifiers for a class/struct/Union in C++. These access specifiers define how the members of the class can be accessed. Of course, any member of a class is accessible within that class(Inside any member function of that same class). Moving ahead to type of access specifiers, they are: Private, Public and protected

Composite type creation

The fundamental data types and their variations are essential, but rather primitive. C and C++ provide tools that allow you to compose more sophisticated data types from the fundamental data types. As you'll see, the most important of these is struct, which is the foundation for class in C++. However, the simplest way to create more sophisticated types is simply to alias a name to another name via typedef.

New

The general form of the new-expression is: new Type; A new-expression returns a pointer to an object of the exact type that you asked for. So if you say new Type, you get back a pointer to a Type. If you say new int, you get back a pointer to an int. If you want a new unsigned char array, you get back a pointer to the first element of that array. The compiler will ensure that you assign the return value of the new-expression to a pointer of the correct type.

sizeof operator

The sizeof operator stands alone because it satisfies an unusual need. sizeof gives you information about the amount of memory allocated for data items. As described earlier in this chapter, sizeof tells you the number of bytes used by any particular variable. It can also give the size of a data type (with no variable name): By definition, the sizeof any type of char (signed, unsigned or plain) is always one, regardless of whether the underlying storage for a char is actually one byte. For all other types, the result is the size in bytes. Note that sizeof is an operator, not a function. If you apply it to a type, it must be used with the parenthesized form shown above, but if you apply it to a variable you can use it without parentheses: i.e int i = sizeof x;

lvalue

The term lvalue originally referred to objects that appear on the left (hence the 'l') hand side of an expression. That definition no longer applies since any const-qualified type is also considered to be an lvalue, but it can never appear on the left hand side of an assignment statement because it can not be modified. So, the term "modifiable lvalue" was created to refer to an lvalue that can be modified, and a const-qualified type does not fall into this category.

this

The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct , or union type. It points to the object for which the member function is called. Static member functions do not have a this pointer.

Symbol table

There are two common and related meaning of symbol tables here. First, there's the symbol table in your object files. Usually, a C or C++ compiler compiles a single source file into an object file with a .obj or .o extension. This contains a collection of executable code and data that the linker can process into a working application or shared library. The object file has a data structure called a symbol table in it that maps the different items in the object file to names that the linker can understand. If you call a function from your code, the compiler doesn't put the final address of the routine in the object file. Instead, it puts a placeholder value into the code and adds a note that tells the linker to look up the reference in the various symbol tables from all the object files it's processing and stick the final location there. Second, there's also the symbol table in a shared library or DLL. This is produced by the linker and serves to name all the functions and data items that are visible to users of the library. This allows the system to do run-time linking, resolving open references to those names to the location where the library is loaded in memory.

asm keyword

This is an escape mechanism that allows you to write assembly code for your hardware within a C++ program. Often you're able to reference C++ variables within the assembly code, which means you can easily communicate with your C++ code and limit the assembly code to that necessary for efficiency tuning or to use special processor instructions. The exact syntax that you must use when writing the assembly language is compiler-dependent and can be discovered in your compiler's documentation.

Dynamic cast

This one is only used to convert object pointers and object references into other pointer or reference types in the inheritance hierarchy. It is the only cast that makes sure that the object pointed to can be converted, by performing a run-time check that the pointer refers to a complete object of the destination type. For this run-time check to be possible the object must be polymorphic. That is, the class must define or inherit at least one virtual function. This is because the compiler will only generate the needed run-time type information for such objects.

Reinterpret cast

To force the pointer conversion, in the same way as the C-style cast does in the background, the reinterpret cast would be used instead. int *r = reinterpret_cast<int*>(&c); // forced conversion This cast handles conversions between certain unrelated types, such as from one pointer type to another incompatible pointer type. It will simply perform a binary copy of the data without altering the underlying bit pattern. Note that the result of such a low-level operation is system-specific and therefore not portable. It should be used with caution if it cannot be avoided altogether.

What is the difference between undefined, unspecified, and implementation-defined behavior ?

Undefined: C++ programs that do not behave in a predictable way. i.e accessing an array beyond its bounds, dereferencing the null pointer, accessing objects after their lifetime ended. 3.4.1 1 implementation-defined behavior: unspecified behavior where each implementation documents how the choice is made 2 EXAMPLE An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right. unspecified behavior: use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance. EXAMPLE An example of unspecified behavior is the order in which the arguments to a function are evaluated. Order of evaluation of the operands of almost all C++ operators (including the order of evaluation of function arguments in a function-call expression and the order of evaluation of the subexpressions within any expression) is unspecified. The compiler can evaluate operands in any order, and may choose another order when the same expression is evaluated again.

Vector

Vectors are sequence containers representing arrays that can change in size. Also, the vector class is a template, which means that it can be efficiently applied to different types. Underneath the hood a Vector might allocate more space than it needs so that it doesn't have to allocate space every time you want to grow it.

stringize operator '#'

When you put a # before an argument in a preprocessor macro, the preprocessor turns that argument into a character array. This, combined with the fact that character arrays with no intervening punctuation are concatenated into a single character array, allows you to make a very convenient macro for printing the values of variables during debugging: #define PR(x) cout << #x " = " << x << "\n"; If you print the variable a by calling the macro PR(a), it will have the same effect as the code: cout << "a = " << a << "\n";

Operator Precedence 11

^ Bitwise XOR (exclusive or) Left-to-right ----------------------------------------------------------------------------------------------------

Keywords

are predefined reserved identifiers (arguably, see StackOverflow What is the meaning of "qualifier"? ) that the language itself assigns some meaning to, rather than leaving free for you to use for your own purposes (i.e. naming your variables, types, namespaces, functions...). volatile and const are both qualifiers and keywords if, class, namespace are keywords but not qualifiers std, main, iostream, x, my_counter are all identifiers but neither keywords nor qualifiers

Preprocessor directives

are used to save typing and to increase the readability of the code. The pre-processed code is often written to an intermediate file. Preprocessor directives are lines included in the code of programs preceded by a hash sign ( # ). ... These preprocessor directives extend only across a single line of code. As soon as a newline character is found, the preprocessor directive is ends. No semicolon ( ; ) is expected at the end of a preprocessor directive.

Operator Precedence 17

throw Throw operator (exceptions throwing, C++ only) Right-to-left ----------------------------------------------------------------------------------------------------

Runtime error detection

is a software verification method that analyzes a software application as it executes and reports defects that are detected during that execution. Runtime error detection can identify defects that manifest themselves only at runtime (for example, file overwrites) and zeroing in on the root causes of the application crashing, running slowly, or behaving unpredictably. Defects commonly detected by runtime error detection include: Race conditions, Exceptions, Resource leaks, Memory leaks , Security attack vulnerabilities (e.g., SQL injection), Null pointers, Uninitialized memory, Buffer overflows

Private vs Public vs protected

class Base { public: int publicMember; protected: int protectedMember; private: int privateMember; }; Everything that is aware of Base is also aware that Base contains publicMember. Only the children (and their children) are aware that Base contains protectedMember. No one but Base is aware of privateMember. The same happens with public, private and protected inheritance. Let's consider a class Base and a class Child that inherits from Base. If the inheritance is public, everything that is aware of Base and Child is also aware that Child inherits from Base. If the inheritance is protected, only Child, and its children, are aware that they inherit from Base. If the inheritance is private, no one other than Child is aware of the inheritance.

Data types

define the way you use storage (memory) in the programs you write. By specifying a data type, you tell the compiler how to create a particular piece of storage, and also how to manipulate that storage. `Primitive Data Types::: i.e Integer, char, bool, float ...

#if, #else and #elif

directives serve to specify some condition to be met in order for the portion of code they surround to be compiled. The condition that follows #if or #elif can only evaluate constant expressions, including macro expressions. For example: Notice how the entire structure of #if, #elif and #else chained directives ends with #endif. The behavior of #ifdef and #ifndef can also be achieved by using the special operators defined and !definedrespectively in any #if or #elif directive: #if TABLE_SIZE>200 #undef TABLE_SIZE #define TABLE_SIZE 200 #elif TABLE_SIZE<50 #undef TABLE_SIZE #define TABLE_SIZE 50 #else #undef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE]; #if defined ARRAY_SIZE #define TABLE_SIZE ARRAY_SIZE #elif !defined BUFFER_SIZE #define TABLE_SIZE 128 #else #define TABLE_SIZE BUFFER_SIZE #endif

Narrowing conversions

from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

Downcasting

is an opposite process, which consists in converting base class pointer (or reference) to derived class pointer. I.e Upcasting Base *pBase; Derived d; pBase = &d; d.print(); Downcasting Derived *pDerived; Base *b; pDerived = (Derived*)b;

Size hierarchy for floating point numbers specifier

is: float, double, and long double. "long float" is not a legal type. There are no short floating-point numbers.

The size hierarchy for integral types

is: short int, int, long int. All the sizes could conceivably be the same, as long as they satisfy the minimum/maximum value requirements. On a machine with a 64-bit word, for instance, all the data types might be 64 bits.

Shift operator

left-shift operator, right-shift operator

Relational Operators

less than (<), greater than (>), less than or equal to (<=), greater than or equal to (>=), equivalent (==), and not equivalent (!=).

Extern const

i.e extern const int bufsize; Normally, the C++ compiler avoids creating storage for a const, but instead holds the definition in its symbol table. When you use extern with const, however, you force storage to be allocated (this is also true for certain other cases, such as taking the address of a const). Storage must be allocated because extern says "use external linkage," which means that several translation units must be able to refer to the item, which requires it to have storage.

Extern

i.e using extern int x; tells the compiler that an object of type int called x exists somewhere. It's not the compilers job to know where it exists, it just needs to know the type and name so it knows how to use it. Once all of the source files have been compiled, the linker will resolve all of the references of x to the one definition that it finds in one of the compiled source files. For it to work, the definition of the x variable needs to have what's called "external linkage", which basically means that it needs to be declared outside of a function (at what's usually called "the file scope") and without the static keyword. Header extern int global_x; void print_global_x(); Source 1 #include "header.h" // it needs to be defined somewhere int global_x; int main() { //set global_x here: global_x = 5; print_global_x(); } Source 2 #include "header.h" void print_global_x() { //print global_x here: std::cout << global_x << std::endl; }

Code reading p_4

int (*(*f4())[10])(); is a function declaration instead of a variable definition. It says "f4 is a function that returns a pointer to an array of 10 pointers to functions that return integers."

directive or pragma

is a language construct that specifies how a compiler (or other translator) should process its input. Directives are not part of the grammar of a programming language, and may vary from compiler to compiler. They can be processed by a preprocessor to specify compiler behavior Preprocessor directives are lines included in the code of programs preceded by a hash sign (#). These lines are not program statements but directives for the preprocessor. The preprocessor examines the code before actual compilation of code begins and resolves all these directives before any code is actually generated by regular statements. These preprocessor directives extend only across a single line of code. As soon as a newline character is found, the preprocessor directive is ends. No semicolon (;) is expected at the end of a preprocessor directive. The only way a preprocessor directive can extend through more than one line is by preceding the newline character at the end of the line by a backslash (\).

Identifier

is a name used to identify a variable, function, class, module, or any other user-defined item. An identifier starts with a letter A to Z or a to z or an underscore (_) followed by zero or more letters, underscores, and digits (0 to 9).

preprocessor

is a simple program that replaces patterns in the source code with other patterns the programmer has defined (using preprocessor directives).

Malloc() vs new / Delete vs Free ?

malloc() vs new 1. new is an operator, while malloc() is a function. 2. new returns exact data type, while malloc() returns void *. 3. new calls constructors( class instances are initalized and deinitialized automatically), while malloc() does not( classes won't get initalized or deinitialized automatically Syntax: int *n = new int(10); // initialization with new() str = (char *) malloc(15); //malloc() free vs delete 1. free( ) is used on resources allocated by malloc( ), or calloc( ) in C 2. Delete is used on resources allocated by new in C++

Specifiers

modify the meanings of the basic built-in types and expand them to a much larger set. There are four specifiers: long, short, signed, and unsigned.

Orthogonality

orthogonality in a programming language means that a relatively small set of primitive constructs can be combined in a relatively small number of ways to build the control and data structures of the languag.The design of C language may be examined from the perspective of orthogonality. The C language is somewhat inconsistent in its treatment of concepts and language structure, making it difficult for the user to learn (and use) the language. Examples of exceptions follow: Structures (but not arrays) may be returned from a function. An array can be returned if it is inside a structure. A member of a structure can be any data type (except void, or the structure of the same type). An array element can be any data type (except void). Everything is passed by value (except arrays). Void can be used as a type in a structure, but a variable of this type cannot be declared in a function.

Internal Linkage vs External Linkage ( static vs extern ) When you write an implementation file (.cpp, .cxx, etc) your compiler generates a translation unit. This is the object file from your implementation file plus all the headers you #included in it. Internal linkage

refers to everything only in scope of a translation unit.

External linkage

refers to things that exist beyond a particular translation unit. In other words, accessible through the whole program, which is the combination of all translation units (or object files).

#ifndef

serves for the exact opposite: the code between #ifndef and #endif directives is only compiled if the specified identifier has not been previously defined. For example: 1 2 3 4 #ifndef TABLE_SIZE #define TABLE_SIZE 100 #endif int table[TABLE_SIZE]; In this case, if when arriving at this piece of code, the TABLE_SIZE macro has not been defined yet, it would be defined to a value of 100. If it already existed it would keep its previous value since the #define directive would not be executed.

Class

the use of class in C++ comes close to being an unnecessary keyword. It's identical to the struct keyword in absolutely every way except one: class defaults to private, whereas struct defaults to public.

If the linkage isn't specified

then the default linkage is extern for non-const symbols and static(internal) for const symbols.

signed and unsigned specifiers

tell the compiler how to use the sign bit with integral types and characters (floating-point numbers always contain a sign). An unsigned number does not keep track of the sign and thus has an extra bit available, so it can store positive numbers twice as large as the positive numbers that can be stored in a signed number.

#include

tells the preprocessor to open the named header file and insert its contents where the #include statement appears. A #include may name a file in two ways: in angle brackets (< >) or in double quotes. Angle brackets → A preprocessing directive of the form # include <h-char-sequence> new-line searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence Double quotes → A preprocessing directive of the form # include "q-char-sequence" new-line The named source file is searched for in an implementation-defined manner. So on most compilers, using the "" first checks your local directory, and if it doesn't find a match then moves on to check the system paths. Using <> starts the search with system headers.

Code reading p_3

typedef double (*(*(*fp3)())[10])(); fp3 a; shows how a typedef saves typing the complicated description every time. It says "An fp3 is a pointer to a function that takes no arguments and returns a pointer to an array of 10 pointers to functions that take no arguments and return doubles." Then it says "a is one of these fp3 types." typedef is generally useful for building complicated descriptions from simple ones.

Typedef

typedef existing-type-description alias-name People often use typedef when data types get slightly complicated, just to prevent extra keystrokes. Here is a commonly-used typedef: typedef unsigned long ulong; One place where typedef comes in handy is for pointer types. As previously mentioned, if you say: int* x, y; This actually produces an int* which is x and an int (not an int*) which is y. That is, the '*' binds to the right, not the left. However, if you use a typedef: typedef int* IntPtr; IntPtr x, y; Then both x and y are of type int*.

Volititle

volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation.[...] Consider this code → int some_int = 100; while(some_int == 100) { //your code } When this program gets compiled, the compiler may optimize this code, if it finds that the program never ever makes any attempt to change the value of some_int, so it may be tempted to optimize the while loop by changing it from while(some_int == 100) to simply while(true) so that the execution could be fast (since the condition in while loop appears to be true always). (if the compiler doesn't optimize it, then it has to fetch the value of some_int (if it's not loaded on a register) and compare it with 100, each time which obviously is a little bit slow.)However, sometimes, optimization (of some parts of your program) may be undesirable, because it may be that someone else is changing the value of some_int from outside the program which compiler is not aware of, since it can't see it; but it's how you've designed it. In that case, compiler's optimization would not produce the desired result.

Can we delete this ?

yes 1. delete operator works only for objects allocated using operator new. If object wasn't allocated with new then behaviour is undefined. 2. Once delete this is done, any member of the deleted object should not be accessed after deletion


Related study sets

MA Real Estate Law and Regulations Q&A

View Set

The Crucible Quotes (can be used for exam review)

View Set

How do you prepare financial statements? (chapter 1)

View Set

TEST #1: Chapter 2 - Review Sheet

View Set

AP U.S. Government and Politics - Unit 1 Progress Check: MCQ

View Set