260 likes | 374 Views
C++ Classes & Data Abstraction. C & C++ differences Class definition Member function definitions Makefiles Utility functions Constructors Destructors. C & C++ Differences. C: procedural programming language Programming is action-oriented Function is basic unit of programming.
E N D
C++ Classes & Data Abstraction • C & C++ differences • Class definition • Member function definitions • Makefiles • Utility functions • Constructors • Destructors
C & C++ Differences • C: procedural programming language • Programming is action-oriented • Function is basic unit of programming
C & C++ Differences • C++: object-oriented programming language • Programming is object-oriented • Class (a user-defined data type) is basic unit of programming • Attributes (data members) • Behaviors or operations (member functions) • Objects are created (instantiated) from the class • Variables are instances of built-in data types
Class Definition //Fraction abstract data type (ADT) definition class Fraction{ public://accessible anywhere in program Fraction(); //member function prototype void set(int, int); //member function prototype void print(); //member function prototype private: //accessible only to member functions int num; //data member int den; //data member }; //terminate class definition with a semicolon
Member Access Specifiers • Public • Any data member or data function declared after this is accessible anywhere in the program • Private • Any data member or data function declared after this is only accessible to member functions of the class • If no specifiers are declared, then the default is private • Can list specifiers in any order • Protected • Used for inheritance
Member Function Definitions //Constructor initializes each data member Fraction::Fraction(){ num = 0; den = 1; } //Set a new Fraction value & check data void Fraction::set(int n , int d ){ if(d == 0) d = 1; if(d < 0) {d = -d; n = -n;} num = n; den = d; } //Print a Fraction void Fraction::print(){ cout << num << " / " << den; }
Driver Program // Driver program to test class Fraction void main(){ //instantiate object t of class Fraction Fraction t; t.print(); // 0 / 1 //set the data t.set( 13, -27); t.print(); // -13 / 27 //attempt invalid data t.set( 99, 0); t.print(); // 99 / 1 } (See complete program at fractionA.txt)
Accessing Class Members class Fraction { public: Fraction(); void print(); int num, den;//Not good programming practice }; Fraction::Fraction() {num = 0; den = 1; } void Fraction::print(){cout<<num<<"/"<<den<<endl;} void main(){ Fraction t; //instantiate a fraction Fraction *ptr = &t; //pointer to t Fraction &ref = t; //reference to t t.num = 1; t.den = 2; t.print(); // 1/2 ptr->num = 2; ptr->den = 3; ptr->print();// 2/3 ref.num = 3; ref.den = 4; ref.print(); // 3/4 }
Accessing Class Members //Use accessor functions instead (accessor.txt): class Fraction { Private: int num, den; public: Fraction(); void print(); void setNum(int); void setDen(int); int getNum(); int getDen(); }; void Fraction::setNum(int n){num = n;} void Fraction::setDen(int d){if(d==0)d=1; den = d;} int Fraction::getNum(){return num;} int Fraction::getDen(){return den;}
Class Exercise • Write a member function for class Function that will multiply two fractions • Here is a sample driver program that uses this function: void main(){ Fraction f1, f2; f1.set(2,3); f2.set(4,5); f1.multiply(f2); f1.print(); // 8/15 f2.print(); // 4/5 }
Multiple Files • Header file (fraction.h) • Declaration of the Fraction class • To prevent multiple inclusions of header file: #ifndef FRACTION_H #define FRACTION_H //header file code #endif • Source-code file (fraction.cpp) • Member function definitions • At top of file: #include "fraction.h" • Driver program (driver.cpp) • Program that uses the Fraction class • At top of file: #include "fraction.h"
Makefile • Don’t forget to: (See makefile) • To change “gcc” to “g++” • To change “.c” to “.cpp” • To tab the beginning of the 2nd line • To leave the 3rd line & last line with a newline out: driver.o fraction.o g++ driver.o fraction.o -o out driver.o: driver.cpp fraction.h g++ -c driver.cpp fraction.o: fraction.cpp fraction.h g++ -c fraction.cpp
Interface & Implementation • Separating interface from implementation • Good software engineering • Easier to modify a program • Changing the implementation will not change the driver program (as long as the interface stays the same) • Clients of a software do not need the to access the class source code, just need the object code & header file • For example, the driver program for class Fraction only needs fraction.h & fraction.o • See makefile
Utility Functions • Not all member functions are public • Utility functions are private • Also called a helper function • Not part of a class interface • Supports the operation of member functions • Not intended to be used by the clients of a class
Utility Functions class Fraction { public: Fraction(); void set(int, int); void print(); private: void reduce(); int num, den; }; void Fraction::set( int n = 0, int d = 1){ if(d==0) d = 1; num = n; den = d; reduce(); }
Utility Functions //Finds GCD using Euclid's algorithm (utility.txt) void Fraction::reduce(){ int a = num; int b = den; while (b!=0){ int temp = a % b; a = b; b = temp; } num = num / a; den = den / a; } void main(){ Fraction t; t.set(6, 4); t.print(); // 3/2 }
Constructors • A constructor is a class member function with the same name as its class • Used to initialize the class data members • Can have several overloaded to initialize data members in different ways • Data to be initialized is put in parenthesis to the right of the objects name • Constructors can also have default arguments
//Example of 3 overloaded constructors class Fraction { int num, den; //default is "private:" public: Fraction(); Fraction(int); Fraction(int, int); //Fraction(int = 0,int = 1);//default arguments }; Fraction::Fraction(){ cout<<"constructor1"<<endl; num = 0; den = 1; } Fraction::Fraction(int n) { cout<<"constructor2"<<endl; num = n; den = 1; } Fraction::Fraction(int n, int d) { cout<<"constructor3"<<endl; num = n; den = d; }
Class Exercise • Using the previous slide’s constructors, what’s the output of this program? void main(){ Fraction f1, f2(2), f3(3,4); Fraction f[5] = {Fraction(), Fraction(6), Fraction(7,8)}; } • What would be the output, if only the constructor with default arguments was used? • See exercise2.txt
Copy Constructor • Called in three cases • When declaring an object in a program Fraction a; Fraction b(a); Fraction *c = new Fraction(b); • When declaring an object in a program (not the default assignment operator) Fraction a; Fraction b = a; • When passing-by-value void multiply(Fraction f)
Copy Constructor • Can create your own copy constructor Fraction(const Fraction &f){ num=f.num; den=f.den; } • Otherwise the computer will create one for you • By default, performed by memberwise copy • Each data member of one object is copied to another object’s data members • Can cause problems with dynamically allocated data members
class Fraction {//What’s the output? public: Fraction(int n=0, int d = 1){ cout<<"constructor with default arguments"<<endl;} Fraction(const Fraction &f){ cout<<"copy constructor"<<endl;} void foo(Fraction f){ Fraction g;} }; void main(){ Fraction f1(3,4); Fraction f2(f1); Fraction f3=f2; f1.foo(f2); } (See exercise3.txt)
Destructors • A destructor is a class member function with the same name as its class with a tilde (~) character in front of it • Called when an object is “destroyed” • When program execution leaves the scope in which the object of that class was instantiated • For global objects & static objects, when the program ends execution • Performs termination housekeeping so memory can be returned to the system
class Fraction { //What’s the output? int num, den; public: Fraction(int); //constructor ~Fraction(); //destructor }; Fraction::Fraction(int n) { num = n; den = 1; cout<<"Con., Fra. ="<<num<<"/"<<den<<endl; } Fraction::~Fraction() { cout<<"Des., Fra. = "<<num<<"/"<<den<<endl; } Fraction f1(10); int main(){ Fraction f2(20); { Fraction f2(30); static Fraction f3(40); { Fraction f3(50); } } return 0; } (See exercise4.txt)
Default Memberwise Copy • Assignment operator (=) can be used to assign one object to another • By default, performed by memberwise copy • Each data member of one object is copied to another object’s data members • Can cause problems with dynamically allocated data members void main(){ Fraction f1, f2(3,4); f1 = f2; f1.print(); // 3/4 f2.print(); // 3/4 }
Default Memberwise Copy • If you were to write it yourself, it would look like this • Will talk more about this format in operator overloading • See complete program at copy.txt const Fraction &operator=(const Fraction &f){ num=f.num; den=f.den; return *this; }