300 likes | 313 Views
Learn about data types in C++, including the use of struct and class for user-defined types. Understand variable declaration and initialization, type checking and coercion, literals, and pointer variables. Explore dynamic and local variables and how to allocate and deallocate memory.
E N D
Advanced Program Design with C++ Part 2: Data types Joey Paquet, 2007-2014
Data types Simple data types Pointers Type checking Type coercion Joey Paquet, 2007-2014
Data types • Highly similar to Java data types • Basic types are not classes (like Java) • Pit trap: different compilers will have different ranges for most basic data types • Some programs potentially will behave differently across different platforms • Hence, lack of portability of C++ programs • User-defined data types using struct(as in C), as well as class(object-oriented programming) • Both are allowed in the same program • In fact, they are almost equivalent, but struct was kept for backward compatibility • A struct can have data members, methods, constructors, destructors, etc • One difference is that a struct sets its members as public by default Joey Paquet, 2007-2014
Data types: simple types size, range and precision Joey Paquet, 2007-2014
Data types: simple types size, range and precision Joey Paquet, 2007-2014
Variable declaration • A variable can be declared for any type valid in the current scope. int x; double y; myClass mc; • Multiple variables of the same type can be declared on the same declaration: intx,y,z; • Any declared name can be referred to thereafter in the scope in which it is declared. Joey Paquet, 2007-2014
Variable declaration • Declarations can include an optional initialization, which can use different syntactical forms: Type a1 {v}; Type a2 = {v}; Type a3 = v; Type a4(v); • All of these are widely used and apparently equivalent. • However: • Some are restricted to use in certain situations. • Only the first one is universally usable, and is actually safer, as it implicitly does some checking of the value passed versus the specified type. int a1 = 1.5; //allowed using truncation int a1 {1.5}; //not allowed, as truncation would happen Joey Paquet, 2007-2014
Data types: type checking and type coercion • C++ uses a manifest typing strategy • Variables and values have types • Values can only be assigned to variables declared as having the same type • However, C++ allows type coercion, i.e. implicitly or explicitly changing the type of variables or values • This loophole, among other things, makes C++ a weakly typed language • Type mismatches • General Rule: Cannot place value of one type into variable of another type intVar = 2.99; // 2 is assigned to intVar! • Only integer part "fits", so that’s all that goes • Called "implicit type casting" or "automatic type conversion" • When using pointers or classes, much more problematic! Joey Paquet, 2007-2014
Data types: literals • Literals • 2, 5.75, ‘Z’, "Hello World“ • Considered "constants": can’t change in program • All literals have an inherent type that can be determined during lexical analysis. • Like many other languages, C++ uses escape sequences for string literals: Joey Paquet, 2007-2014
Data types: pointer variables • Variables contain a specific value, e.g., an integer. • Pointer variables hold a memory addresses as their values. • Apointer contains the memory address of a portion of memory that in turn contains a specific value. • For any type T, T* is the type “pointer to T”, i.e. a variable of type T* can hold the address of an object of type T. inti = 99; int* p = &i; cout << *p << endl; • Two operators on pointers: • Dereferencing operator: *, e.g. *p refers to the object pointed to by the pointer. • Address operator: &, e.g. &irefers to the address of the first memory cell holding an object. 99 i (int) &i p (*int) Joey Paquet, 2007-2014
Data types: pointer variables • Consider: int*p1, *p2, v1, v2; • Pointer assignment: p1 = &v1; • Sets pointer variable p1 to "point to" variable v1 • "p1 equals address of v1" • Or "p1 points to v1“ v1 = 0; *p1 = 42; • p1 and v1 refer to same memory cell Joey Paquet, 2007-2014
Data types: pointer variables • Pointer assignment vs value assignment: int v1 = 42; int v2 = 9; int *p2 = &v2; int*p1 = &v1; • Pointer assignment: p2 = p1; • Assigns one pointer to another • "Make p2point to where p1 points“ • Value assignment: *p2 = *p1; • Assigns "value pointed to" by p1, to "valuepointed to" by p2 Joey Paquet, 2007-2014
Data types: pointer variables • Dynamic variables • Allocated with new operator, deallocated with the delete operator • Allocated and destroyed explicitly while program runs • Local variables • Declared within function definition • Not dynamic • Allocated on the stack when code block is entered (e.g. function call) • Destroyed when code block is exited (e.g. function call completes) • Often called "automatic" variables • Allocation and deallocation controlled for you Joey Paquet, 2007-2014
Data types: pointer variables • The operator new creates dynamically allocated values that can then be pointed to by pointer variables. • The value created is a nameless pointer value. • Allocated on the heap, or freestore through the runtime system’s interaction with the operating system. • All dynamically allocated variables need to be carefully managed by the programmer. • C++ does not have garbage collection. • Dynamically allocated variables need to be allocated and deallocated manually • Similar to C’s malloc Joey Paquet, 2007-2014
Data types: pointer variables int *p1, p2; p1 = new int; *p1 = 42; p2 = p1; Joey Paquet, 2007-2014
Data types: pointer variables *p2 = 53; *p1 = new int; *p1 = 88; Joey Paquet, 2007-2014
Data types: pointer variables • If the type used as parameter is of class type: • Constructor is called for new object • Can invoke different constructor with initializer arguments: MyClass *myPtr;myPtr= new MyClass(32.0, 17); • Can still initialize non-class types: int*n; n = new int(17);//Initializes *n to 17 Joey Paquet, 2007-2014
Data types: pointer variables • Pointers are full-fledged types • Can be used just like other types • Can be function parameters • Can be returned from functions • Example: int* findOtherPointer(int* p); • This function declaration: • Has "pointer to an int" parameter • Returns "pointer to an int" Joey Paquet, 2007-2014
Data types: pointer variables • Potential problem if freestore runs out of memory • Older compilers: • Test if null returned by call to new:int *p;p = new int;if (p == NULL){ cout << "Error: Insufficient memory.\n"; exit(1);} • Later compilers (C++98 and after) : • newthrows exception bad_alloc try { int * myarray= new int[1000]; } catch (bad_alloc&) { cout << "Error allocating memory." << endl; } Joey Paquet, 2007-2014
Data types: pointer variables • To deallocate dynamic memory, use the delete operator • When value no longer needed • Returns memory to freestore • Example:int *p;p = new int(5); //allocate memory… //Some processing…delete p; //deallocate memoryp = NULL; //prevents dangling pointer errors • Deallocates dynamic memory "pointed to by pointer p“ • p is then a dangling pointer • If not deleted before the variable goes out of scope, memory is not freed, which creates a memory leak. • Plus, dereferencing a dangling pointer leads to unpredictable results, ranging from getting a seemingly random value to program crash. • Managing dangling pointers and deallocating dynamically allocated memory is a very important aspect of proper C++ programming. Joey Paquet, 2007-2014
Pointer arithmetic • Can perform arithmetic operations on pointers • Used to navigate arrays (covered later) • Example:int *d; d = new int[10]; • d refers to: address of new int[10] • d + 1refers to: address of new int[10] + 1*sizeof(int) • d + 2refers to: address of new int[10] + 2*sizeof(int) • d[i] == *(&d[0]+j) == *(a+j) Joey Paquet, 2007-2014
references Joey Paquet, 2007-2014
Reference • Pointers are very powerful, as they allow: • A variable to refer a value held by another variable. • A variable to refer to different values held by different variables in time. • Pass information around without having to copy it. • However, due to their power, pointers bring additional complexities: • Must use a special syntax (*, &, ->) • Possibility of dangling pointers, wild pointers, null pointers. • References are pointer variables that eliminate some of the disadvantages of pointers, at the cost of eliminating some of their power. • Pointer arithmetic cannot be applied to a reference. • Any operation applied to a reference is actually applied onto the variable it refers to, including assignment. • Hence, references must be initialized upon declaration and cannot be changed afterwards. • Furthermore, given a reference int& r {v1}, &r returns a pointer to the object referred to by r. Thus, we cannot even have a pointer to a reference. Joey Paquet, 2007-2014
type casting Joey Paquet, 2007-2014
Data types: explicit type casting • C++ provides operators for explicit type coercion, or type casting static_cast<double>intVar • Explicitly "casts" intVarto doubletype doubleVar= static_cast<double>intVar1/intVar2; • Casting forces double-precision division to take place among two integer variables. • Equivalent in meaning to the following C syntax, even though the C++ cast operation is checked at compile time and is thus less prone to runtime errors doubleVar= (double)intVar1/intVar2; Joey Paquet, 2007-2014
Data types: explicit type casting • Different kinds of explicit type casting operations: • static_cast<Type>(expression) • General-purpose type casting • const_cast<Type>(expression) • Cast-out “constantness” • dynamic_cast<Type>(expression) • Runtime-checked conversion of pointers and references within a single class hierarchy. Used for downcasting from a superclass to a subclass • reinterpret_cast<Type>(expression) • Implementation-dependent casting, performs a binary copy and assigns the new type to the resulting binary copied value. Highly unsafe and error-prone. Joey Paquet, 2007-2014
Data types: upcasting and downcasting • When dealing with classes and subclasses, one can declare objects of a supertype and manipulate them as one of its subclasses • Problem: subclass members are undefined in superclass GeometricObject ---------------------- area perimeter void displayGeometricObject(GeometricObject& g) { cout << "The radius is " << g.getRadius() << endl; cout << "The diameter is " << g.getDiameter() << endl; cout << "The width is " << g.getWidth() << endl; cout << "The height is " << g.getHeight() << endl; cout << "The area is " << g.getArea() << endl; cout << "The perimeter is " << g.getPerimeter() << endl; } Circle ------------ radius diameter Rectangle ------------- width height Joey Paquet, 2007-2014
Data types: upcastingand downcasting • May want to use static_cast: • This successfully compiles, but will fail at runtime if the object passed was originally of a type that does not contain the members referred to in the code. • static_cast makes a static (compile-time) type cast, but correct runtime behavior is not verified. void displayGeometricObject(GeometricObject& g) { GeometricObject* p = &g; cout << "The radius is " << static_cast<Circle*>(p)->getRadius() << endl; cout << "The diameter is " << static_cast<Circle*>(p)->getDiameter() << endl; cout << "The width is " << static_cast<Rectangle*>(p)->getWidth() << endl; cout << "The height is " << static_cast<Rectangle*>(p)->getHeight() << endl; cout << "The area is " << g.getArea() << endl; cout << "The perimeter is " << g.getPerimeter() << endl; } Joey Paquet, 2007-2014
Data types: upcastingand downcasting • Use dynamic_cast to downcast into a subclass • dynamic_cast works on pointers • Does runtime checking to verify that the cast is successful • Also deals with polymorphic types and the virtual methods table at runtime Joey Paquet, 2007-2014
References • Y. Daniel Liang, Introduction to Programming with C++ (Chapter 1, 11, 13, 15), Peason, 2014. • Bjarne Stroustrup, The C++ Programming Language (Chapter 6, 7, 11, 22), Addison-Wesley, 2013. Joey Paquet, 2007-2014