C++/Class/virtual function — различия между версиями

Материал из C\C++ эксперт
Перейти к: навигация, поиск
м (1 версия: Импорт контента...)
 
(нет различий)

Версия 17:21, 25 мая 2010

A base class reference is used to access a virtual function

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 virtual void vfunc() {
   cout << "This is base"s vfunc().\n";
 }

};

class derived1 : public base { public:

 void vfunc() {
   cout << "This is derived1"s vfunc().\n";
 }

};

class derived2 : public base { public:

 void vfunc() {
   cout << "This is derived2"s vfunc().\n";
 }

};

// Use a base class reference parameter. void f(base &r) {

 r.vfunc();

}

int main() {

 base b;
 derived1 d1;
 derived2 d2;
  
 f(b); // pass a base object to f()
 f(d1); // pass a derived1 object to f()
 f(d2); // pass a derived2 object to f()
  
 return 0;

}


 </source>


Abstract classes by virtual function with no body

<source lang="cpp">

  1. include <iostream>

using namespace std; class Animal{ public:

   Animal(int health = 100);
   virtual void Greet() const = 0;   //pure virtual member function
   virtual void DisplayHealth() const;

protected:

   int m_Health;

}; Animal::Animal(int health): m_Health(health){} void Animal::DisplayHealth() const{

   cout << "Health: " << m_Health << endl;

} class Orc : public Animal{ public:

   Orc(int health = 120);
   virtual void Greet() const;

}; Orc::Orc(int health):

   Animal(health)

{} void Orc::Greet() const {

   cout << "The orc grunts hello.\n";

} int main() {

   Animal* pAnimal = new Orc();
   pAnimal->Greet();
   pAnimal->DisplayHealth();
   return 0;

}


 </source>


Call parent virtual function

<source lang="cpp">

  1. include <iostream>
  2. include <string>

using namespace std; class Book { public:

 virtual string getDescription() { return "Book"; }

}; class Paperback : public Book { public:

 virtual string getDescription() { 
   return "Paperback " + Book::getDescription(); 
 }

}; class Romance : public Paperback { public:

 virtual string getDescription() { 
   return "Romance " + Paperback::getDescription(); 
 }

}; class Technical : public Book { public:

 virtual string getDescription() { 
   return "Technical " + Book::getDescription();
 }

}; int main() {

 Romance novel;
 Book book;
 cout << novel.getDescription() << endl;
 cout << book.getDescription(); 

}


 </source>


Illustration of the Use of Virtual Inheritance

<source lang="cpp">

  1. include <iostream>

using namespace std; typedef int HANDS; enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown } ; class Animal {

 public:
   Animal(int);
   virtual ~Animal() { cout << "Animal destructor...\n"; }
   virtual int GetAge() const { return itsAge; }
   virtual void SetAge(int age) { itsAge = age; }
 private:
   int itsAge;

}; Animal::Animal(int age): itsAge(age) {

  cout << "Animal constructor...\n";

} class Horse : virtual public Animal {

 public:
   Horse(COLOR color, HANDS height, int age);
   virtual ~Horse() { cout << "Horse destructor...\n"; }
   virtual void Whinny()const { cout << "Whinny!... "; }
   virtual HANDS GetHeight() const { return itsHeight; }
   virtual COLOR GetColor() const { return itsColor; }
 protected:
   HANDS itsHeight;
   COLOR itsColor;

}; Horse::Horse(COLOR color, HANDS height, int age): Animal(age), itsColor(color),itsHeight(height) {

  cout << "Horse constructor...\n";

} class Bird : virtual public Animal {

 public:
   Bird(COLOR color, bool migrates, int age);
   virtual ~Bird() {cout << "Bird destructor...\n";  }
   virtual void Chirp()const { cout << "Chirp... ";  }
   virtual void Fly()const{ cout << "I can fly! I can fly! I can fly! "; }
   virtual COLOR GetColor()const { return itsColor; }
   virtual bool GetMigration() const { return itsMigration; }
 protected:
   COLOR itsColor;
   bool itsMigration;

}; Bird::Bird(COLOR color, bool migrates, int age): Animal(age), itsColor(color), itsMigration(migrates) {

  cout << "Bird constructor...\n";

} class Pegasus : public Horse, public Bird {

 public:
   void Chirp()const { Whinny(); }
   Pegasus(COLOR, HANDS, bool, long, int);
   virtual ~Pegasus() {cout << "Pegasus destructor...\n";}
   virtual long GetNumberBelievers() const
        { return  itsNumberBelievers; }
   virtual COLOR GetColor()const { return Horse::itsColor; }
 private:
   long itsNumberBelievers;

}; Pegasus::Pegasus(

  COLOR aColor,
  HANDS height,
  bool migrates,
  long NumBelieve,
  int age):
  Horse(aColor, height,age),
  Bird(aColor, migrates,age),
  Animal(age*2),
  itsNumberBelievers(NumBelieve)

{

  cout << "Pegasus constructor...\n";

} int main() {

  Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2);
  int age = pPeg->GetAge();
  cout << "This pegasus is " << age << " years old.\n";
  delete pPeg;
  return 0;

}


 </source>


Implementing Pure Virtual Functions

<source lang="cpp">

  1. include <iostream>

using namespace std; class Shape {

 public:
   Shape(){}
   virtual ~Shape(){}
   virtual double GetArea() = 0;
   virtual double GetPerim()= 0;
   virtual void Draw() = 0;
 private:

}; void Shape::Draw() {

  cout << "Abstract drawing mechanism!\n";

} class Circle : public Shape {

 public:
   Circle(int radius):itsRadius(radius){}
   virtual ~Circle(){}
   double GetArea() { return 3.14 * itsRadius * itsRadius; }
   double GetPerim() { return 2 * 3.14 * itsRadius; }
   void Draw();
 private:
   int itsRadius;
   int itsCircumference;

}; void Circle::Draw() {

  cout << "Circle drawing routine here!\n";
  Shape::Draw();

} class Rectangle : public Shape {

 public:
   Rectangle(int len, int width):
   itsLength(len), itsWidth(width){}
   virtual ~Rectangle(){}
   double GetArea() { return itsLength * itsWidth; }
   double GetPerim() {return 2*itsLength + 2*itsWidth; }
   virtual int GetLength() { return itsLength; }
   virtual int GetWidth() { return itsWidth; }
   void Draw();
 private:
   int itsWidth;
   int itsLength;

}; void Rectangle::Draw(){

  for (int i = 0; i<itsLength; i++){
     for (int j = 0; j<itsWidth; j++)
        cout << "x ";
  cout << "\n";
  }
  Shape::Draw();

}

class Square : public Rectangle {

 public:
   Square(int len);
   Square(int len, int width);
   virtual ~Square(){}
   double GetPerim() {return 4 * GetLength();}

}; Square::Square(int len): Rectangle(len,len) {} Square::Square(int len, int width):Rectangle(len,width){

  if (GetLength() != GetWidth())
     cout << "Error, not a square... a Rectangle??\n";

} int main() {

  Shape * sp;
  sp = new Circle(5);
  sp->Draw();
  delete sp;
  
  sp = new Rectangle(4,6);
  sp->Draw();
  delete sp;
  
  sp = new Square (5);
  sp->Draw();
  delete sp;
  return 0;

}


 </source>


Multiple Virtual Functions Called in Turn

<source lang="cpp">

  1. include <iostream>

using namespace std; class Mammal {

 public:
    Mammal():itsAge(1) {  }
    virtual ~Mammal() { }
    virtual void Speak() const { cout << "Mammal speak!\n"; }
 protected:
    int itsAge;

}; class Dog : public Mammal {

 public:
   void Speak()const { cout << "Woof!\n"; }

}; class Cat : public Mammal {

 public:
   void Speak()const { cout << "Meow!\n"; }

};

class Horse : public Mammal {

 public:
   void Speak()const { cout << "Winnie!\n"; }

}; class Pig : public Mammal {

 public:
   void Speak()const { cout << "Oink!\n"; }

}; int main() {

  Mammal* theArray[5];
  Mammal* ptr;
  ptr = new Dog;
  theArray[0] = ptr;
  ptr = new Cat;
  theArray[1] = ptr;
  ptr = new Horse;
  theArray[2] = ptr;
  ptr = new Pig;
  theArray[3] = ptr;
  ptr = new Mammal;
  theArray[4] = ptr;
  
  for (int i=0;i<5;i++)
     theArray[i]->Speak();
  return 0;

}


 </source>


Override non-virtual function

<source lang="cpp">

  1. include <iostream>

using namespace std; class Base {

public:
  void display(void) { cout << "This is the base class" << endl; };

}; class Derived: public Base {

public:
  void display(void) { cout << "This is the derived class" << endl; };

}; int main(void) {

  Derived my_class;
  my_class.display();

}


 </source>


Pure Virtual Functions as a prototype

<source lang="cpp">

  1. include <iostream>

using namespace std;

class number { protected:

 int val;

public:

 void setval(int i) { val = i; }
  
 // show() is a pure virtual function
 virtual void show() = 0;

};

class hextype : public number { public:

 void show() {
   cout << hex << val << "\n";
 }

};

class dectype : public number { public:

 void show() {
   cout << val << "\n";
 }

};

class octtype : public number { public:

 void show() {
   cout << oct << val << "\n";
 }

};

int main() {

 dectype d;
 hextype h;
 octtype o;
  
 d.setval(20);
 d.show(); // displays 20 - decimal
  
 h.setval(20);
 h.show(); // displays 14 - hexadecimal
  
 o.setval(20);
 o.show();  // displays 24 - octal
  
 return 0;

}


 </source>


The Virtual Attribute Is Inherited

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 virtual void vfunc() {
   cout << "This is base"s vfunc().\n";
 }

};

class derived1 : public base { public:

 void vfunc() {
   cout << "This is derived1"s vfunc().\n";
 }

};

/* derived2 inherits virtual function vfunc()

  from derived1. */

class derived2 : public derived1 { public:

 // vfunc() is still virtual
 void vfunc() {
   cout << "This is derived2"s vfunc().\n";
 }

};

int main() {

 base *p, b;
 derived1 d1;
 derived2 d2;
  
 // point to base
 p = &b;
 p->vfunc(); // access base"s vfunc()
  
 // point to derived1
 p = &d1;
 p->vfunc(); // access derived1"s vfunc()
  
 // point to derived2
 p = &d2;
 p->vfunc(); // access derived2"s vfunc()
  
 return 0;

}


 </source>


Using Virtual Functions to control the behaviour

<source lang="cpp">

  1. include <iostream>

using namespace std;

class convert { protected:

 double val1;  // initial value
 double val2;  // converted value

public:

 convert(double i) {
   val1 = i;
 }
 double getconv() { return val2; }
 double getinit() { return val1; }
  
 virtual void compute() = 0;

};

// Liters to gallons. class l_to_g : public convert { public:

 l_to_g(double i) : convert(i) { }
 void compute() {
   val2 = val1 / 3.7854;
 }

};

// Fahrenheit to Celsius class f_to_c : public convert { public:

 f_to_c(double i) : convert(i) { }
 void compute() {
   val2 = (val1-32) / 1.8;
 }

};

int main() {

 convert *p;  // pointer to base class
  
 l_to_g lgob(4);
 f_to_c fcob(70);
  
 // use virtual function mechanism to convert
 p = &lgob;
 cout << p->getinit() << " liters is ";
 p->compute();
 cout << p->getconv() << " gallons\n";  // l_to_g
  
 p = &fcob;
 cout << p->getinit() << " in Fahrenheit is ";
 p->compute();
 cout << p->getconv() << " Celsius\n";  // f_to_c
  
 return 0;

}


 </source>


Using Virtual Methods

<source lang="cpp">

  1. include <iostream>

using namespace std; class Mammal {

 public:
    Mammal():itsAge(1) { cout << "Mammal constructor..." << endl; }
    virtual ~Mammal() { cout << "Mammal destructor..." << endl; }
    void Move() const { cout << "Mammal move one step" << endl; }
    virtual void Speak() const { cout << "Mammal speak!" << endl; }
 protected:
    int itsAge;

}; class Dog : public Mammal {

 public:
   Dog() { cout << "Dog Constructor..." << endl; }
   virtual ~Dog() { cout << "Dog destructor..." << endl; }
   void WagTail() { cout << "Wagging Tail..." << endl; }
   void Speak()const { cout << "Woof!" << endl; }
   void Move()const { cout << "Dog moves 5 steps..." << endl; }

}; int main() {

  Mammal *pDog = new Dog;
  pDog->Move();
  pDog->Speak();
  return 0;

}


 </source>


Virtual base classes.

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 int i;

};

// derived1 inherits base as virtual. class derived1 : virtual public base { public:

 int j;

};

// derived2 inherits base as virtual. class derived2 : virtual public base { public:

 int k;

};

class derived3 : public derived1, public derived2 { public:

 int sum;

};

int main() {

 derived3 ob;
  
 ob.i = 10; // now unambiguous
 ob.j = 20;
 ob.k = 30;
  
 // unambiguous
 ob.sum = ob.i + ob.j + ob.k;
  
 // unambiguous
 cout << ob.i << " ";
  
 cout << ob.j << " " << ob.k << " ";
 cout << ob.sum;
  
 return 0;

}


 </source>


Virtual Copy Constructor

<source lang="cpp">

  1. include <iostream>

using namespace std; class Mammal {

 public:
    Mammal():itsAge(1) { cout << "Mammal constructor..." << endl; }
    virtual ~Mammal() { cout << "Mammal destructor..." << endl; }
    Mammal (const Mammal & rhs);
    virtual void Speak() const { cout << "Mammal speak!" << endl; }
    virtual Mammal* Clone() { return new Mammal(*this); }
    int GetAge()const { return itsAge; }
 protected:
    int itsAge;

}; Mammal::Mammal (const Mammal & rhs):itsAge(rhs.GetAge()) {

  cout << "Mammal Copy Constructor..." << endl;

} class Dog : public Mammal {

 public:
   Dog() { cout << "Dog constructor..." << endl; }
   virtual ~Dog() { cout << "Dog destructor..." << endl; }
   Dog (const Dog & rhs);
   void Speak()const { cout << "Woof!" << endl; }
   virtual Mammal* Clone() { return new Dog(*this); }

}; Dog::Dog(const Dog & rhs): Mammal(rhs) {

  cout << "Dog copy constructor..." << endl;

} class Cat : public Mammal {

 public:
   Cat() { cout << "Cat constructor..." << endl; }
   ~Cat() { cout << "Cat destructor..." << endl; }
   Cat (const Cat &);
   void Speak()const { cout << "Meow!" << endl; }
   virtual Mammal* Clone() { return new Cat(*this); }

}; Cat::Cat(const Cat & rhs): Mammal(rhs) {

  cout << "Cat copy constructor..." << endl;

} enum ANIMALS { MAMMAL, DOG, CAT}; const int NumAnimalTypes = 3; int main() {

  Mammal *theArray[NumAnimalTypes];
  Mammal* ptr;
  ptr = new Dog;
  theArray[0] = ptr;
  ptr = new Cat;
  theArray[1] = ptr;
  ptr = new Mammal;
  theArray[2] = ptr;
  Mammal *OtherArray[NumAnimalTypes];
  for (int i=0;i<NumAnimalTypes;i++)
  {
     theArray[i]->Speak();
     OtherArray[i] = theArray[i]->Clone();
  }
  for (int i=0;i<NumAnimalTypes;i++)
     OtherArray[i]->Speak();
  return 0;

}


 </source>


Virtual function and two subclasses

<source lang="cpp">

  1. include <iostream>

using namespace std; class Base { public:

 virtual void who(void) {  
   cout << "Base\n";  
 }  

};

class first_d : public Base { public:

 void who(void) {  
   cout << "First derivation\n";  
 }  

};

class second_d : public Base { // who() not defined };

main(void) {

 Base base_obj;  
 Base *p;  
 first_d first_obj;  
 second_d second_obj;  
    
 p = &base_obj;  
 p->who(); 
    
 p = &first_obj;  
 p->who();   
    
 p = &second_obj;  
 p->who();  
    
 return 0;  

}


 </source>


virtual function from base and derived classes

<source lang="cpp">

  1. include <iostream>
  2. include <string.h>

using namespace std; class Base {

public:
  virtual void show_message(void) { cout << "Base class message" << endl; };
  virtual void show_reverse(void) = 0;

}; class Derived : public Base {

public:
  virtual void show_message(void) { cout << "Derived class message" << endl; };
  virtual void show_reverse(void) { cout << strrev("Derived class message") << endl; };

}; int main(void) {

  Base *poly = new Derived;
  poly->show_message();
  poly->show_reverse();

}


 </source>


Virtual function in three level inheritance

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 virtual void vfunc() {
   cout << "This is base"s vfunc().\n";
 }

};

class derived1 : public base { public:

 void vfunc() {
   cout << "This is derived1"s vfunc().\n";
 }

};

class derived2 : public derived1 { public: };

int main() {

 base *p, b;
 derived1 d1;
 derived2 d2;
  
 // point to base
 p = &b;
 p->vfunc(); // access base"s vfunc()
  
 // point to derived1
 p = &d1;
 p->vfunc(); // access derived1"s vfunc()
  
 // point to derived2
 p = &d2;
 p->vfunc(); // use derived1"s vfunc()
  
 return 0;

}


 </source>


virtual functions accessed from pointer

<source lang="cpp">

  1. include <iostream>
 using namespace std;  
 class Base{  
    public:  
       virtual void show(){ cout << "Base\n"; }  
   };  
 class Derv1 : public Base{  
    public:  
       void show(){ cout << "Derv1\n"; }  
 };  
 class Derv2 : public Base{  
    public:  
       void show(){ cout << "Derv2\n"; }  
   };  
 int main(){  
    Derv1 dv1;           
    Derv2 dv2;           
    Base* ptr;           
   
    ptr = &dv1;          
    ptr->show();         
   
    ptr = &dv2;          
    ptr->show();         
    return 0;  
 }
 
   
 </source>


Virtual Functions and Polymorphism

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 virtual void vfunc() {
   cout << "This is base"s vfunc().\n";
 }

};

class derived1 : public base { public:

 void vfunc() {
   cout << "This is derived1"s vfunc().\n";
 }

};

class derived2 : public base { public:

 void vfunc() {
   cout << "This is derived2"s vfunc().\n";
 }

};

int main() {

 base *p, b;
 derived1 d1;
 derived2 d2;
  
 // point to base
 p = &b;
 p->vfunc(); // access base"s vfunc()
  
 // point to derived1
 p = &d1;
 p->vfunc(); // access derived1"s vfunc()
  
 // point to derived2
 p = &d2;
 p->vfunc(); // access derived2"s vfunc()
  
 return 0;

}


 </source>


Virtual Functions Are Hierarchical

<source lang="cpp">

  1. include <iostream>

using namespace std;

class base { public:

 virtual void vfunc() {
   cout << "This is base"s vfunc().\n";
 }

};

class derived1 : public base { public:

 void vfunc() {
   cout << "This is derived1"s vfunc().\n";
 }

};

class derived2 : public base { public: // vfunc() not overridden by derived2, base"s is used };

int main() {

 base *p, b;
 derived1 d1;
 derived2 d2;
  
 // point to base
 p = &b;
 p->vfunc(); // access base"s vfunc()
  
 // point to derived1
 p = &d1;
 p->vfunc(); // access derived1"s vfunc()
  
 // point to derived2
 p = &d2;
 p->vfunc(); // use base"s vfunc()
  
 return 0;

}


 </source>


virtual functions with person class

<source lang="cpp">

  1. include <iostream>
 using namespace std;  
 class person{  
    protected:  
       char name[40];  
    public:  
       void getName()  
          { cout << "   Enter name: "; cin >> name; }  
       void putName()  
          { cout << "Name is: " << name << endl; }  
       virtual void getData() = 0;
       virtual bool isOutstanding() = 0;
   };  
 class student : public person{  
    private:  
       float gpa;             
    public:  
       void getData(){  
          person::getName();  
          cout << "   Enter student"s GPA: "; cin >> gpa;  
       }  
       bool isOutstanding()  
       { 
          return (gpa > 3.5) ? true : false; 
       }  
 };  
 class professor : public person{  
    private:  
       int numPubs;             
    public:  
       void getData(){  
          person::getName();  
          cout << "   Enter number of professor"s publications: ";  
          cin >> numPubs;  
       }  
       bool isOutstanding()  
       { 
          return (numPubs > 100) ? true : false; 
       }  
 };  
 int main(){  
    person* persPtr[100];
    int n = 0;           
    char choice;  
   
    do {  
       cout << "Enter student or professor (s/p): ";  
       cin >> choice;  
       if(choice=="s")   
          persPtr[n] = new student;     
       else                             
          persPtr[n] = new professor;   
       persPtr[n++]->getData();         
       cout << "   Enter another (y/n)? ";
       cin >> choice;  
    } while( choice=="y" );          
   
    for(int j=0; j<n; j++){                                
       persPtr[j]->putName();           
       if( persPtr[j]->isOutstanding() )  
          cout << "   This person is outstanding\n";  
    }  
    return 0;  
 }
 
   
 </source>


virtual members

<source lang="cpp">

  1. include <iostream>

using namespace std; class CPolygon {

 protected:
   int width, height;
 public:
   void set_values (int a, int b)
   { width=a; height=b; }
   virtual int area ()
   { return (0); }

}; class CRectangle: public CPolygon {

 public:
   int area ()
     { return (width * height); }

}; class CTriangle: public CPolygon {

 public:
   int area ()
     { return (width * height / 2); }

}; int main () {

 CRectangle rect;
 CTriangle trgl;
 CPolygon poly;
 CPolygon * ppoly1 = &rect;
 CPolygon * ppoly2 = &trgl;
 CPolygon * ppoly3 = &poly;
 ppoly1->set_values (4,5);
 ppoly2->set_values (4,5);
 ppoly3->set_values (4,5);
 cout << ppoly1->area() << endl;
 cout << ppoly2->area() << endl;
 cout << ppoly3->area() << endl;
 return 0;

}


 </source>