C++/Class/virtual function — различия между версиями
Admin (обсуждение | вклад) м (1 версия: Импорт контента...) |
|
(нет различий)
|
Версия 17: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
<source lang="cpp">
- 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">
- 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">
- 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();
}
</source>
Illustration of the Use of Virtual Inheritance
<source lang="cpp">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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();
}
</source>
Virtual function in three level inheritance
<source lang="cpp">
- 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">
- 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">
- 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">
- 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">
- 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">
- 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;
}
</source>