C++/Class/virtual function
Версия от 14:21, 25 мая 2010; (обсуждение)
Содержание
- 1 A base class reference is used to access a virtual function
- 2 Abstract classes by virtual function with no body
- 3 Call parent virtual function
- 4 Illustration of the Use of Virtual Inheritance
- 5 Implementing Pure Virtual Functions
- 6 Multiple Virtual Functions Called in Turn
- 7 Override non-virtual function
- 8 Pure Virtual Functions as a prototype
- 9 The Virtual Attribute Is Inherited
- 10 Using Virtual Functions to control the behaviour
- 11 Using Virtual Methods
- 12 Virtual base classes.
- 13 Virtual Copy Constructor
- 14 Virtual function and two subclasses
- 15 virtual function from base and derived classes
- 16 Virtual function in three level inheritance
- 17 virtual functions accessed from pointer
- 18 Virtual Functions and Polymorphism
- 19 Virtual Functions Are Hierarchical
- 20 virtual functions with person class
- 21 virtual members
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 = ▭
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;
}