310 likes | 544 Views
C++ Classes: Part II. Use of const Composition Friend functions & classes The this pointer Dynamic memory allocation Static class members. Constant Objects. Principle of least privilege Users should be given no more privilege than necessary to perform a job Good software engineering
E N D
C++ Classes: Part II • Use of const • Composition • Friend functions & classes • The this pointer • Dynamic memory allocation • Static class members
Constant Objects • Principle of least privilege • Users should be given no more privilege than necessary to perform a job • Good software engineering • Declaring a constant object • const Fraction f(1,2); • Can only be accessed by member functions that are also declared const
Constant Member Functions • Function prototype void print() const; • Function definition void Fraction::print() const{ cout<<num<<"/"<<den<<endl; } • Constructors & destructors cannot be declared constant • Const member functions cannot modify the object (not allowed by compiler)
Constant Example • Example driver program void main(){ Fraction f1(1,2); const Fraction f2(3,4); f1.multiply(f2); f2.multiply(f1); //gives an error f1.print(); f2.print(); } (See complete program at const.txt)
Constant Data Member • Must modify the constructor to initialize a constant data member class Fraction { const int count; int num, den; public: Fraction(int = 0, int = 0, int = 1); void print() const; }; Fraction::Fraction(int c, int n, int d):count(c){ num = n; den = d; }
Constant Data Member • Alternative way to initialize data members Fraction::Fraction(int c, int n, int d) :count(c), num(n), den(d){} • Print statement void Fraction::print() const{ cout<<count<<":"<<num<<"/"<<den<<endl; } • See complete program at constDataMember.txt
Constant Data Member • Example driver program void main(){ Fraction f1(1,1,2), f2(2,3,4), f3(3,5,6); f1.print(); f2.print(); f3.print(); } /* 1:1/2 2:3/4 3:5/6 */
Passing Parameters • When passing a parameter to a method • Call-by-reference more efficient than call-by-value • Call-by-value creates a “local copy” of the variable with the “copy constructor” • Call-by-reference simple maintains a “place-holder”, as the actual changes are make to the variable in the calling routine • Not a big deal with simple data types (int, etc.) • Can be a big deal with user-defined data types (that contain a lot of data)
For Improved Efficiency • When possible, make parameters call-by-reference • Can speed up execution for some data types • Potential problem • You define the interface for the class’s methods • You have the team write the actual methods • The team is not so bright, so they don’t implement the methods properly
Potential Problem void main(){ Fraction a(2,3); Fraction b(5,7); a.mul(b); a.print(); b.print(); } //output is ?? class Fraction { int i[2]; public: Fraction(int n=0, int d=1){ i[0]=n; i[1]=d;} void mul(Fraction &f){ i[0]=i[0]*f.i[0]; i[1]=i[1]*f.i[1]; f.i[1]=0; } void print() const{ cout<<i[0]<<'/'<<i[1]<<endl; } }; See potentialProblem.txt
Solution: use “const” • Still use reference parameter • Make the parameter a “const”, so cannot change • Solution to mul method void mul( const Fraction &f ){ i[0]=i[0]*f.i[0]; i[1]=i[1]*f.i[1]; f.i[1]=0; /*will be flagged as an error*/ }
Composition • A class can have objects of another class as data members • Example: • Fred (of class Person) has a birthday (of class Date)
#include <iostream> #include <cstring> using namespace std; class Date { int month, day, year; public: Date(int = 1, int = 1, int = 2001); void print() const; }; Date::Date(int m, int d, int y):month(m), day(d), year(y){} void Date::print() const{ cout<<month<<"/"<<day<<"/"<<year<<endl; }
class Person{ char name[20]; const Date birthday; /*Date class*/ public: Person(char[] = "Akira", int = 2, int = 2, int = 2002); void print() const; }; Person::Person(char n[], int m, int d, int y): birthday(m,d,y) { /*Date class*/ int len = strlen(n); strncpy(name,n,len); name[len]='\0'; } void Person::print() const{ cout<<name<<"'s birthday is "; birthday.print(); /*Date class*/ }
Example Driver Program void main(){ Person p1, p2("Toriyama", 10, 31, 1980); p1.print(); p2.print(); } /* Akira's birthday is 2/2/2002 Toriyama's birthday is 10/31/1980 */ (See complete program at composition.txt)
Class Exercise 1 • Class handout (exercise1.txt)
Friend Function • Declaring a function as a friend of a class allows that function to access the private data members of that class
class Person{ friend void changeAge(Person &, int); //appears 1st by convention char name[20]; int age; public: Person(char[] = "Hayao", int = 0); void print() const; }; Person::Person(char n[], int a):age(a){ int len = strlen(n); strncpy(name,n,len); name[len]='\0'; } void Person::print() const{ cout<<name<<" is "<<age<<" years old"<<endl; } void changeAge(Person &p, int x){ p.age+=x; }
Example Driver Program void main(){ Person p("Miyazaki", 55); p.print(); changeAge(p, -5); p.print(); } /* Miyazaki is 55 years old Miyazaki is 50 years old */ (See complete program at friendFunction.txt)
Friend Classes • Allows class1 access to class2’s private data members class Date { friend class Person; int month, day, year; public: Date(int = 1, int = 1, int = 2001); void print() const; }; (See complete program at friendClass.txt)
Friend Classes class Person{ char name[20]; const Date birthday; public: Person(char[] = "Akira", int = 2, int = 2, int = 2002); void print() const; }; void Person::print() const{ cout<<name<<"'s birthday is "; cout<<birthday.month<<"/"<<birthday.day<<"/“ <<birthday.year<<endl; //birthday.print(); //can directly access Date’s private members }
The This Pointer • Every object has access to its own address through a pointer called “this” • Can be used to reference class data members & member functions • Also can be used to enable cascaded member calls
The This Pointer class Fraction { int num, den; public: Fraction(int = 0, int = 1); void print() const; Fraction &multiply(const Fraction &); Fraction ÷(const Fraction &); }; Fraction::Fraction(int n, int d):num(n),den(d){} void Fraction::print() const{ cout << this->num << " / "<< (*this).den <<endl; //reference to data members }
The This Pointer Fraction &Fraction::multiply(const Fraction &f){ num = num * f.num; den = den * f.den; return *this; } Fraction &Fraction::divide(const Fraction &f){ num = num * f.den; den = den * f.num; return *this; } //Enables cascaded member calls (See complete program at this.txt)
The This Pointer int main(){ Fraction f, f1(1,2), f2(2,2), f3(5,2), f4(2,3); f = f1.multiply(f2).multiply(f3).divide(f4); //cascaded member calls //evaluated from left to right f.print(); f1.print(); f2.print(); f3.print(); f4.print(); return 0; } /* 30 / 16 30 / 16 2 / 2 5 / 2 2 / 3 */
Dynamic Memory Allocation • new & delete operators replace C’s malloc & free function calls • new operator • Allocates memory on the heap • Calls the constructor for the object • Returns a pointer to the object on the heap • If the heap if full, new returns 0 • delete operator • Deallocates memory from the heap • Calls the destructor
Dynamic Memory Allocation • Example program (newDelete.txt) int main(){ Fraction *f1; f1 = new Fraction(10); Fraction *f2 = new Fraction(20, 30); Fraction *f3 = new Fraction[40]; f1->print(); // 10/1 f2->print(); // 20/30 f3[39].print(); // 0/1 delete f1; delete f2; delete []f3; return 0; }
Static Class Members • A variable shared by all members of its class • “Class-wide” information • See static.txt class Fraction { int num, den; static int count; public: Fraction(int = 0, int = 1); ~Fraction(); static int getCount(); };
Static Class Members int Fraction::count=0; //initialize static member int Fraction::getCount(){return count;} //accessor function Fraction::Fraction(int n, int d):num(n), den(d){ count++;//constructor increments count } Fraction::~Fraction(){ count--;//destructor decrements count }
int main(){ cout<<"count="<<Fraction::getCount()<<endl; //count=0 Fraction a; { Fraction b; Fraction c; cout<<"count="<<b.getCount()<<endl; //count=3 cout<<"count="<<c.getCount()<<endl; //count=3 } cout<<"count="<<a.getCount()<<endl; //count=1 return 0; }
Class Exercise • Class handout (exercise2.txt)