110 likes | 220 Views
Trade-off: Efficiency. A virtual function uses dynamic binding (in other words, late binding ). This requires more storage and makes the program runs slower. In C++ , by default, a member function is not virtual functions unless specified by the modifier, virtual .
E N D
Trade-off: Efficiency A virtual function uses dynamic binding (in other words, late binding). This requires more storage and makes the program runs slower. • In C++, by default, a member function is not virtual functions unless specified by the modifier, virtual. • In Java, all member functions are virtual.
Virtual function, overriding Function, defining need to redefine, otherwise likes() defined in the base class will be inherited and it will call the food() defined in the bases class, which is not virtual. Inheritance call Change non-virtual to virtual, food() at Cat:: call Overloading ( Change non-virtual to virtual) Pet:: likes();food(); goes();voice(); likes();food(); goes();voice(); likes();food(); goes();voice(); Cat:: Dog:: call likes();food(); goes();voice(); likes();food(); goes();voice(); Wolf:: BigCat:: Inheritance Backwards Inheritance
int main() { // Pet tommy("Tommy"); // Abstract class, can't be instantiated Dog lucky("Lucky"); cout << "\n" << lucky.I() << " is a Dog.\n"; lucky.goes(); lucky.likes(); Cat mimi("Mimi"); cout << "\n" << mimi.I() << " is a Cat.\n"; mimi.goes(); mimi.likes(); BigCat simba("Simba"); cout << "\n" << simba.I() << " is a BigCat.\n"; simba.goes(); simba.likes(); cout << endl; return 0; } Main Lucky is a Dog. Lucky goes Woof!! Woof!! Lucky likes ????! Mimi is a Cat. Mimi goes Meow!! Meow!! Mimi likes fish! Simba is a BigCat. Simba goes Grrr!! Grrr!! Simba likes zebras!
Base class -- Cat:: fish Meow likes();food();goes();voice(); int main() { Cat mimi("Mimi"), BigCat simba("Simba"); Cat t("temp"); t = mimi; t.goes(); t.likes(); cout << endl; simba.goes(); simba.likes(); cout << endl; t = simba; t.goes(); t.likes(); .... } Assignment and Virtual functions virtual virtual likes();food(); goes();voice(); zebras Grrrr Derived class -- BigCat:: Mimi goes Meow!! Meow!! Mimi likes fish! Simba goes Grrr!! Grrr!! Simba likes zebras! Simba goes Meow!! Meow!! Simba likes fish!
Base class -- Cat:: fish Meow likes();food();goes();voice(); int main() { ..... Cat mimi("Mimi"), BigCat simba("Simba"); Cat *p; p = &mimi; p->goes(); p->likes(); cout << endl; p = &simba; p->goes(); p->likes(); .... } Pointers and Virtual functions virtual virtual likes();food(); goes();voice(); zebras Grrrr Derived class -- BigCat:: Mimi goes Meow!! Meow!! Mimi likes fish! Simba goes Grrr!! Grrr!! Simba likes zebras!
A potential problem if used as base class class Dept { public: Dept(int idn); // Constructor; int my_id; }; Dept::Dept(int id) // Constructor; :my_id(id) {} It seems that there is no need to have a destructor (and the Big-Three).
class CS: public Dept { public: CS(int n); // Constructor, n is the no of courses CS(const CS & c); // Copy constructor; CS & operator=(const CS & c); // Overloading =; ~CS(); // Destructor; int *my_courses; int my_n; }; CS::CS(int n) // Constructor :Dept(5555), my_n(n) { my_courses = new int[n]; } CS::~CS() // Destructor; { delete [] my_courses; cout << my_n << " courses deleted\n"; // Just for demo; } A derived class with a dynamic array
CS::CS(const CS & a) // Copy constructor :Dept(5555) { my_n = a.my_n; my_courses = new int[my_n]; for (int i=0; i< my_n; i++) my_courses[i] = a.my_courses[i]; } CS & CS::operator=(const CS & a) { if (this == & a) // This handles a = a situation; return *this; // Nothing to be done; Dept::operator=(a); // Assign values defined in the base, Dept; my_n = a.my_n; delete [] my_courses; // Remove the old array; my_courses = new int[my_n]; // Create a new arrays; for (int i=0; i< my_n; i++) // Copy the contents from a { my_courses[i] = a.my_courses[i]; } return *this; } A copy constructor and operator =
void print(CS c) { cout << "\n" << c.my_id << endl; for (int i=0; i< c.my_n; i++) cout << c.my_courses[i] << ","; cout << "\n\n"; } int main() { int n=3; CS a(n),b(4); for (int i=0; i< n; i++) a.my_courses[i] = 1000+i+1; b = a; print(b); return 0; } No problem, so far. 5555 1001,1002,1003, 3 courses deleted 3 courses deleted 3 courses deleted Press any key to continue
int f() { CS *pc; pc = new CS(21); delete pc; cout << endl; Dept *pd; pd = new CS(40); delete pd; cout << endl; return 0; } Problems come out!! 21 courses deleted Press any key to continue Destructor of Dept, which is a default one, will be called. We have lost 40 courses (integers)!!!
The body of ~Dept() class Dept { public: Dept(int idn); // Constructor; int my_id; virtual ~Dept(){}; // Can't be pure }; ........ int f() { CS *pc; pc = new CS(21); delete pc; cout << endl; Dept *pd; pd = new CS(40); delete pd; cout << endl; return 0; } Solution 21 courses deleted 40 courses deleted Press any key to continue Destructor of CS will be called.