C++ Tutorial/Class/virtual function

Материал из C\C++ эксперт
Версия от 13:29, 25 мая 2010; Admin (обсуждение | вклад) (1 версия: Импорт контента...)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Access base class"s virtual if derived class does not redefine it

<source lang="cpp">#include <iostream> using namespace std;

class BaseClass { public:

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

};

class DerivedClass1 : public BaseClass { public:

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

};

class DerivedClass2 : public BaseClass { // who() not defined };

int main() {

 BaseClass base_obj; 
 BaseClass *p; 
 DerivedClass1 DerivedClass1_obj; 
 DerivedClass2 DerivedClass2_obj; 

 p = &base_obj; 
 p->who();  // access BaseClass"s who() 

 p = &DerivedClass1_obj; 
 p->who(); // access DerivedClass1"s who() 

 p = &DerivedClass2_obj; 
 p->who(); /* access BaseClass"s who() because 
              DerivedClass2 does not redefine it */ 

 return 0; 

}</source>

Base
First derivation
Base

A pure virtual function

<source lang="cpp">#include <iostream>

  1. include <cstring>

using namespace std;

class Shape {

 double width; 
 double height; 

 char name[20]; 

public:

 Shape() { 
   width = height = 0.0; 
   strcpy(name, "unknown"); 
 } 

 Shape(double w, double h, char *n) { 
   width = w; 
   height = h; 
   strcpy(name, n); 
 } 

 Shape(double x, char *n) { 
   width = height = x; 
   strcpy(name, n); 
 } 

 void display() { 
   cout << "Width and height are " << width << " and " << height << "\n"; 
 } 

 double getWidth() { return width; } 
 double getHeight() { return height; } 
 void setWidth(double w) { width = w; } 
 void setHeight(double h) { height = h; } 
 char *getName() { return name; } 

 virtual double area() = 0; 

};

class Triangle : public Shape {

 char style[20];

public:

 Triangle() { 
   strcpy(style, "unknown"); 
 } 

 Triangle(char *str, double w, double h) : Shape(w, h, "triangle") { 
   strcpy(style, str); 
 } 
  
 Triangle(double x) : Shape(x, "triangle") { 
   strcpy(style, "isosceles");  
 } 

 double area() { 
   return getWidth() * getHeight() / 2; 
 } 

 void showStyle() { 
   cout << "Triangle is " << style << "\n"; 
 } 

};

class Rectangle : public Shape { public:

 Rectangle(double w, double h) : Shape(w, h, "rectangle") { }  
 
 Rectangle(double x) : Shape(x, "rectangle") { }  

 bool isSquare() { 
   if(getWidth() == getHeight()) 
      return true; 
   return false; 
 } 

 double area() { 
   return getWidth() * getHeight(); 
 } 

};

int main() {

 Shape *shapes[4]; 
 
 shapes[0] = &Triangle("right", 8.0, 12.0);  
 shapes[1] = &Rectangle(10);  
 shapes[2] = &Rectangle(10, 4);  
 shapes[3] = &Triangle(7.0);  
 
 for(int i=0; i < 4; i++) {  
   cout << "object is " << shapes[i]->getName() << "\n";  
   cout << "Area is " << shapes[i]->area() << "\n\n";  
 }  

 return 0; 

}</source>

object is triangle
Area is 24.5
object is triangle
Area is 24.5
object is triangle
Area is 24.5
object is triangle
Area is 24.5

A virtual function

<source lang="cpp">#include <iostream> using namespace std;

class BaseClass { public:

 virtual void who() { // specify a virtual function 
   cout << "Base\n"; 
 } 

};

class DerivedClass1 : public BaseClass { public:

 void who() { // redefine who() for DerivedClass1  
   cout << "First derivation\n"; 
 } 

};

class DerivedClass2 : public BaseClass { public:

 void who() { // redefine who() for DerivedClass2 
   cout << "Second derivation\n"; 
 } 

};

int main() {

 BaseClass base_obj; 
 BaseClass *p; 
 DerivedClass1 DerivedClass1_obj; 
 DerivedClass2 DerivedClass2_obj; 

 p = &base_obj; 
 p->who();  // access BaseClass"s who 

 p = &DerivedClass1_obj; 
 p->who(); // access DerivedClass1"s who 

 p = &DerivedClass2_obj; 
 p->who();  // access DerivedClass2"s who 
  
 return 0; 

}</source>

Base
First derivation
Second derivation

Class with only virtual methods

<source lang="cpp">#include <iostream>

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

class Circle : public Shape
{
public:
    Circle(int radius):itsRadius(radius){}
    ~Circle(){}
    long GetArea() { return 3 * itsRadius * itsRadius; }
    long GetPerim() { return 9 * itsRadius; }
    void Draw();
private:
    int itsRadius;
    int itsCircumference;
};

void Circle::Draw()
{
    std::cout << "Circle drawing \n";
}


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

void Rectangle::Draw()
{
    for (int i = 0; i<itsLength; i++)
    {
        for (int j = 0; j<itsWidth; j++)
            std::cout << "x ";

        std::cout << "\n";
    }
}

class Square : public Rectangle
{
public:
    Square(int len);
    Square(int len, int width);
    ~Square(){}
    long GetPerim() {return 4 * GetLength();}
};

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

Square::Square(int len, int width):Rectangle(len,width)
{
    if (GetLength() != GetWidth())
        std::cout << "Error, not a square... a Rectangle??\n";
}

int main()
{
    Shape * sp;

    sp = new Circle(5);
    sp->Draw();
    
    sp = new Rectangle(4,6);
    sp->Draw();
    
    sp = new Square(5);
    sp->Draw();
    return 0;
}</source>
Circle drawing
x x x x x x
x x x x x x
x x x x x x
x x x x x x
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x

Implementing pure virtual functions

<source lang="cpp">#include <iostream>

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

void Shape::Draw()
{
    std::cout << "Abstract drawing mechanism!\n";
}

class Circle : public Shape
{
public:
    Circle(int radius):itsRadius(radius){}
    ~Circle(){}
    long GetArea() { return 3 * itsRadius * itsRadius; }
    long GetPerim() { return 9 * itsRadius; }
    void Draw();
private:
    int itsRadius;
    int itsCircumference;
};

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

class Rectangle : public Shape
{
public:
    Rectangle(int len, int width):
        itsLength(len), itsWidth(width){}
    virtual ~Rectangle(){}
    long GetArea() { return itsLength * itsWidth; }
    long 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++)
            std::cout << "x ";

        std::cout << "\n";
    }
    Shape::Draw();
}

class Square : public Rectangle
{
public:
    Square(int len);
    Square(int len, int width);
    ~Square(){}
    long GetPerim() {return 4 * GetLength();}
};

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

Square::Square(int len, int width):Rectangle(len,width){
    if (GetLength() != GetWidth())
        std::cout << "Error, not a square... a Rectangle??\n";
}

int main()
{
    Shape * sp;

    sp = new Circle(5);
    sp->Draw();
    sp = new Rectangle(4,6);
    sp->Draw();
    sp = new Square (5);
    sp->Draw();
    return 0;
}</source>
Circle drawing routine here!
Abstract drawing mechanism!
x x x x x x
x x x x x x
x x x x x x
x x x x x x
Abstract drawing mechanism!
x x x x x
x x x x x
x x x x x
x x x x x
x x x x x
Abstract drawing mechanism!

Multiple virtual member functions called in turn

<source lang="cpp">#include <iostream>

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

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


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


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

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

int main()
{
    Animal* theArray[5];
    Animal* ptr;
    int i;
    theArray[0] = new Dog;
    theArray[1] = new Cat;
    theArray[2] = new Horse;
    theArray[3] = new Pig;
    theArray[4] = new Animal;
    
    for (i=0;i<5;i++)
        theArray[i]->Speak();
    return 0;
}</source>
Woof!
Meow!
Winnie!
Oink!
Animal speak!

Use Virtual Functions to change the method behaviour

<source lang="cpp">#include <iostream> using namespace std; class Base { public:

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

};

class first_d : public Base { public:

 void who(void) { // define who() relative to first_d  
   cout << "First derivation\n";  
 }  

};

class second_d : public Base { public:

 void who(void) { // define who() relative to second_d  
   cout << "Second derivation\n";  
 }  

};

int main(void) {

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

}</source>

Use virtual function to calculate area for different shapes

<source lang="cpp">#include <iostream>

 using namespace std;
 class Shape {  
 protected:  
   double x, y;  
 public:  
   void set_dim(double i, double j=0) {  
     x = i;  
     y = j;  
   }  
   virtual void show_area(void) {  
     cout << "No area computation defined ";  
     cout << "for this class.\n";  
   }  
 } ;  
      
 class triangle : public Shape {  
   public:  
     void show_area(void) {  
       cout << "Triangle with height ";  
       cout << x << " and base " << y;  
       cout << " has an area of ";  
       cout << x * 0.5 * y << ".\n";  
     }  
 };  
      
 class square : public Shape {  
   public:  
     void show_area(void) {  
       cout << "Square with dimensions ";  
       cout << x << "x" << y;  
       cout << " has an area of ";  
       cout << x *  y << ".\n";  
      }  
 };  
      
 class circle : public Shape {  
   public:  
     void show_area(void) {  
       cout << "Circle with radius ";  
       cout << x;  
       cout << " has an area of ";  
       cout << 3.14 * x * x;  
     }  
 } ;  
      
 main(void)  
 {  
   Shape *p;  
   triangle t; 
   square s;  
   circle c;  
      
   p = &t;  
   p->set_dim(10.0, 5.0);  
   p->show_area();  
      
   p = &s;  
   p->set_dim(10.0, 5.0);  
   p->show_area();  
      
   p = &c;  
   p->set_dim(9.0);  
   p->show_area();  
      
   return 0;  
 }</source>

Why Virtual Functions: one interface, multiple methods

<source lang="cpp">#include <iostream>

   using namespace std;       
 class Shape {  
 protected:  
   double x, y;  
 public:  
   void set_dim(double i, double j) {  
     x = i;  
     y = j;  
   }  
   virtual void show_area(void) {  
     cout << "No area computation defined ";  
     cout << "for this class.\n";  
   }  
 } ;  
      
 class triangle : public Shape {  
   public:  
     void show_area(void) {  
       cout << "Triangle with height ";  
       cout << x << " and base " << y;  
       cout << " has an area of ";  
       cout << x * 0.5 * y << ".\n";  
     }  
 };  
      
 class square : public Shape {  
   public:  
     void show_area(void) {  
       cout << "Square with dimensions ";  
       cout << x << "x" << y;  
       cout << " has an area of ";  
       cout << x *  y << ".\n";  
     }  
 };  
      
 main(void)  
 {  
   Shape *p;  
      
   triangle t; 
   square s;  
      
   p = &t;  
   p->set_dim(10.0, 5.0);  
   p->show_area();  
   p = &s;  
   p->set_dim(10.0, 5.0);  
   p->show_area();  
      
   return 0;  
 }</source>