c++ features and constructs ch. 3 except 3.2, 3.4, 3.9, 3.11

37
C++ Features and Constructs Ch. 3 except 3.2, 3.4, 3.9, 3.11

Upload: bertina-cooper

Post on 17-Dec-2015

219 views

Category:

Documents


0 download

TRANSCRIPT

C++ Features and Constructs

Ch. 3 except 3.2, 3.4, 3.9, 3.11

Scope

• Programs are built of nested "scopes".– Sometimes called "scope blocks" or "name

spaces"

• Inner scopes "hide" or "shadow" outer scopes.

• Variables are only accessible when they are "in scope".

Kinds of scope

• Three main kinds of scope in C++– Local: function or block– Class: extent of the class– File: only available within a file

• Also – Function scope: labels and gotos– Global scope

Scope Exampleslong x;

float y;

int z;

void fn(char c, int x) { // parameter hides global x

extern int z; // refer to global z

double y = 3.14; // shadows global y

{

char y; // shadows double y from above

y = c; // assigns to inner y

::y = 0.3; // assign to global y

}

y = y/3.0; // assign to local y

z++; // increment global z

}

Class Scope

• Class members and methods are available anywhere in the class without forward declaration (a.k.a. prototype)

• Examples:Vector::Vector(int x, int y) {

Vector::x = x;

Vector::y = y;

}

New Topic: Optional Arguments

• Arguments to a function can be given default values.

• Example:int echo(int value=0) {

return value;

}

echo(10); // returns 10

echo(); // returns 0

Optional Arguments (cont’d)

• Optional arguments must be at the end of the argument list

• When might this be useful?

New Topic: Overloading Functions

• Functions have signatures– A function's signature is

• the function's name

• its parameter list (types and orders)

• C++ allows functions with different signatures to have different definitions.

Overloading Functions

• Examples:

int power(int a, int n);

int power(double a, int n);

• What's a problem here?

Function Call Resolution:

1. If there's an exact match, call that version

2. Match through standard type promotions

3. Match through standard conversions

4. Match through user supplied conversions (section 8.7)

5. No match (error)

C++ is Strongly Typed.

• C++ is strongly typed– All variables must have a type before being

used.

• Types must match before function calls can be allowed

Standard Promotions

• Promotions take types and increase their resolution

• Examples:– short to int– int to long– ...

Standard conversions

• Conversions convert a variable to a different type

• Examples:– int to float– float to int– ...

Example

• What happens in the following fragment:

float x, a;

int y;

a = x + y;

C++ is Strongly Typed

• Types still need to match – Consider two functions like:

int operator +(int lhs, int rhs);

float operator +(float lhs, float rhs);

– One of these must match for a = x + y;

When Does Conversion Happen?

• When does the compiler do this? – Arithmetic– Function calls (argument type conversion)– Return values

Explicit Type Conversion (Type Casting)

• In C++, casts look like:

<type-name>( <expression> )

int x = int(3.14);

New Topic: More About References

• References can be variables as well as parameters to functions

• They must be initialized when declared

• Example:– int a;– int &ra = a; // ra is a reference to a

References (cont’d)

• A reference must be initialized to an "lvalue" – an lvalue is anything that can appear on the left-

hand side of an assignment statement

New Topic: Read-only Variables (const)

• Variables can be declared read-only

• Example:const <type name> <variable name> = <value>;

const int forever_one = 1;

• Read-only variables are initialized at declaration but cannot be changed at run-time.

Read-only Parameters (const)

• Parameters can be read-only too.

• Example:int foo(const int x) { ... }

• How does this come in handy?

New Topic: Dynamic Allocation in C++

• Use operator new in place of malloc()

<pointer variable> = malloc(<type>);

<pointer variable> = new <type>;

• new understands about class constructors!

new []

• new can be used for arrays too

• Example:– int * array = new int [10];

delete vs. free

free(<pointer variable>);

delete <pointer variable>;

Dynamic Allocation Examples

int * int_ptr = new int;

int * ten_ptr = new int(10);

int [] int_array = new int [10];

Vector * vptr = new Vector(5, 6); // calls vector constructor!

delete int_ptr;

delete ten_ptr;

delete [] int_prt;

delete vptr;

A Longer Example: Fractions

• Fractions are numbers of the form:

• numerator/denominator

• Fractions have several properties:– The numerator and denominator are both

integers.– The denominator cannot be 0– Arithmetic operations are well defined for

fractions.

Questions about Fractions

• How should a fraction be stored?– A pair of integers, numerator and denominator

• What operations should we support for fractions?– +, -, - (unary), etc.– <, >, ==– reduce(), print()

class Fraction {

public:

Fraction();

Fraction(int);

Fraction(int, int);

print();

Fraction operator +(Fraction);

Fraction operator -();

Fraction operator -(Fraction);

int operator <(Fraction);

int operator >(Fraction);

int operator ==(Fraction);

private:

int numerator, denominator;

};

Constructor Considerations

• What if denominator is zero?– Exit the program

• We have three cases:– no arguments (default to 0/1)– one argument (numerator)– two arguments (numerator and denominator)

• Anything else?

ConstructorsFraction::Fraction() {

numerator = 0;

denominator = 0;

}Fraction::Fraction(int num) {

numerator = num;

denominator = 1;

}

Fraction::Fraction(int num, int denom) {

numerator = num;

if (denom == 0)

exit(1);

denominator = denom;

}

print()

• Print() should print the fraction in the form numerator/denominator to stdout

void print() {

cout << numerator << “/” << denominator;

}

Fraction Fraction::operator +(Fraction right) {

Fraction answer;

int left_num, right_num;

left_num = right.denominator * numerator;

right_num = denominator * right.numerator;

answer.denominator = right.denominator * denominator;

answer.numerator = left_num + right_num;

return answer;

}

Fraction Fraction::operator -() {

Fraction answer(-numerator, denominator);

return answer;

}

Fraction Fraction::operator -(Fraction right) {

Fraction answer;

int left_num, right_num;

left_num = right.denominator * numerator;

right_num = denominator * right.numerator;

answer.denominator = right.denominator * denominator;

answer.numerator = left_num - right_num;

return answer;

}

An Easier Way to Subtract Fractions

Fraction Fraction::operator -(Fraction right) {Fraction left = *this;

return (left + -right);

}

int Fraction::operator <(Fraction right) {

int left_int = numerator * right.denominator;

int right_int = right.numerator * denominator;

return (left_int < right_int);

}

int Fraction::operator >(Fraction right) {

int left_int = numerator * right.denominator;

int right_int = right.numerator * denominator;

return (left_int > right_int);

}

int Fraction::operator ==(Fraction right) {

Fraction left = (*this);

return !(left < right || left > right);

}