C++/Class/virtual function

Материал из C\C++ эксперт
Перейти к: навигация, поиск

A base class reference is used to access a virtual function

   
#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;
}


Abstract classes by virtual function with no body

  
#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;
}


Call parent virtual function

  
#include <iostream>
#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(); 
}


Illustration of the Use of Virtual Inheritance

  
#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;
}


Implementing Pure Virtual Functions

  
#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;
}


Multiple Virtual Functions Called in Turn

  
#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;
}


Override non-virtual function

  
#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();
}


Pure Virtual Functions as a prototype

   
#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;
}


The Virtual Attribute Is Inherited

   
#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;
}


Using Virtual Functions to control the behaviour

   
#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;
}


Using Virtual Methods

  
#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;
}


Virtual base classes.

   
#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;
}


Virtual Copy Constructor

  
#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;
}


Virtual function and two subclasses

  
#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;  
}


virtual function from base and derived classes

   
#include <iostream>
#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();
}


Virtual function in three level inheritance

   
#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;
}


virtual functions accessed from pointer

  
#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;  
  }


Virtual Functions and Polymorphism

   
#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;
}


Virtual Functions Are Hierarchical

   
#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;
}


virtual functions with person class

  
#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;  
  }


virtual members

  
#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;
}