/* *derive2.cpp *Date : 2013-9-24 *Author: sjin *Mail:[email protected] */ #include <iostream> #define N 0 using namespace std; /*知识点: * 1、隐藏基类的方法(就是在派生类中重新实现函数的定义) * 2、当基类的方法被覆盖时,仍可通过限定方法名来调用它,如下格式: * baseclass::Method(); */ /*基类*/ class Manmal{ public: //Manmal():itsAge(2),itsWeight(5){ cout << " create Manmal object..."<<endl;} //~Manmal(){cout << " destroy Manmal object..."<<endl;} void Move() const { cout << "Manmal move one step..." << endl;} void Move(int distance) const { cout << "Manmal Move '" << distance << "' steps..." << endl; } private: int itsAge; int itsWeight; }; /*派生类*/ class Dog : public Manmal { public: //Dog() {cout << " create Dog object..." << endl;} //~Dog() {cout << " destroy Dog object..."<< endl;} /*隐藏了基类的Move()方法*/ void Move() const { cout << "Dog move 5 steps..." << endl; cout << "隐式调用基类方法(start):" << endl; Manmal::Move(); Manmal::Move(1000); cout << "隐式调用基类方法(end):" << endl; } }; int main() { Manmal bigAnimal; Dog Fido; cout << "**********Manmal bigAnimal*************" << endl; bigAnimal.Move(); bigAnimal.Move(2); cout << "**********Dog Fido*************" << endl; Fido.Move(); //Fido.Move(2); /* 上面将会出现下面的错误 * derive2.cpp:56: error: no matching function for call to ‘Dog::Move(int)’ * derive2.cpp:43: note: candidates are: void Dog::Move() const * 也就是说: 覆盖任一个重载的方法后,该方法的其他所有版本都会被隐藏。 * 如果补希望他们被隐藏,必须对其进行覆盖。 */ /*显式调用被隐藏基类的方法*/ cout << "显式调用基类方法(start):" << endl; Fido.Manmal::Move(); Fido.Manmal::Move(200); cout << "显式调用基类方法(end):" << endl; }输出如下:
**********Manmal bigAnimal************* Manmal move one step... Manmal Move '2' steps... **********Dog Fido************* Dog move 5 steps... 隐式调用基类方法(start): Manmal move one step... Manmal Move '1000' steps... 隐式调用基类方法(end): 显式调用基类方法(start): Manmal move one step... Manmal Move '200' steps... 显式调用基类方法(end):
/* *virtual.cpp *Date : 2013-9-20 *Author: sjin *Mail:[email protected] */ #include <iostream> using namespace std; /*知识点: * 1、如何创建虚函数? * 在函数声明前加上virtual 关键字 * 2、使用虚方法的意义 * 基类中如果声明了虚方法,说明它的派生类中有可能会覆盖这个方法。 * 3、如果在基类中将一个成员方法标记为虚方法,还需要在派生类中将它标记为虚方法吗? * 不需要,方法被声明为虚方法后,如果在派生类覆盖它,它仍是虚方法。在派生类继续 * 将其标记为虚方法是个不错的主意,但是没有必要这么作,这样使代码更容易理解。 * */ class Manmal { public: Manmal():itsAge() { cout << "Manmal constrctor...\n";} virtual ~Manmal() { cout << "Manmal destructor...\n";} void Move() const { cout << "Manmal move one step\n";} virtual void Speak() const { cout << "Manmal speak!\n";} protected: int itsAge; }; class Dog :public Manmal{ public: Dog() { cout << " Dog constrctor...\n";} virtual ~Dog() { cout << " Dog destructor..\n";} void WagTail() { cout << " Wagging Tail...\n";} void Speak() const { cout << "Dog woof!\n";} void Move() const { cout << "Dog moves 5 steps ...\n";} }; int main() { /*创建一个信的dog对象,并返回该对象的指针,然后将该指针付给一个 * Manmal指针。 * 这是多态的本质,例如:可创建很多类型的窗口,包括对话框,可滚动 * 窗库和列表框,然后给每种窗口定义一个虚方法draw().通过创建一个窗口指针, * 并将对话框和其他的派生对象赋給指针,就可以通过调用draw(),而不用考虑运行 * 时指针只想的实际对象类型,程序将调用正确的draw()方法。 * */ Manmal *pDog = new Dog; pDog->Move(); pDog->Speak();/*虚方法,被覆盖*/ /*释放对象*/ delete pDog; return 0; }
Manmal constrctor... Dog constrctor... Manmal move one step Dog woof! Dog destructor.. Manmal destructor...
/* *virtual2.cpp *Date : 2013-9-20 *Author: sjin *Mail:[email protected] */ #include <iostream> using namespace std; /*依次调用多个虚方法。 * 通过基类指针访问派生类的方法*/ class Manmal { public: // Manmal():itsAge() { cout << "Manmal constrctor...\n";} // virtual ~Manmal() { cout << "Manmal destructor...\n";} virtual void Speak() const { cout << "Manmal speak!\n";} protected: int itsAge; }; class Dog :public Manmal{ public: void Speak() const { cout << "Dog woof!\n";} }; class cat :public Manmal{ public: void Speak() const { cout << "cat Meow!\n";} }; class Horse :public Manmal{ public: void Speak() const { cout << "Horse Winnie!\n";} }; class Pig :public Manmal{ public: void Speak() const { cout << "Dog Qink!\n";} }; int main() { /*创建一个信的dog对象,并返回该对象的指针,然后将该指针付给一个 * Manmal指针。 * 这是多态的本质,例如:可创建很多类型的窗口,包括对话框,可滚动 * 窗库和列表框,然后给每种窗口定义一个虚方法draw().通过创建一个窗口指针, * 并将对话框和其他的派生对象赋給指针,就可以通过调用draw(),而不用考虑运行 * 时指针只想的实际对象类型,程序将调用正确的draw()方法。 * */ Manmal * theArray[5] = {NULL}; Manmal * ptr; int choice ,i; for(i = 0; i<5; i++){ cout << "1) Dog 2) cat 3) Horse 4) Pig 请输入:"; cin >> choice; switch(choice){ case 1: ptr = new Dog; break; case 2: ptr = new cat; break; case 3: ptr = new Horse; break; case 4: ptr = new Pig; break; default:ptr = new Manmal;break; } theArray[i] = ptr; } for(i=0;i<5;i++){ theArray[i]->Speak(); delete theArray[i]; } return 0; } [jsh@localhost class]$ ./a.out 1) Dog 2) cat 3) Horse 4) Pig 请输入:1 1) Dog 2) cat 3) Horse 4) Pig 请输入:2 1) Dog 2) cat 3) Horse 4) Pig 请输入:3 1) Dog 2) cat 3) Horse 4) Pig 请输入:4 1) Dog 2) cat 3) Horse 4) Pig 请输入:5 Dog woof! cat Meow! Horse Winnie! Dog Qink! Manmal speak!
虚函数和纯虚函数:
所谓虚函数就是在编译的时候不确定要调用哪个函数,而是动态决定将要调用哪个函数。它的作用就是为了能让这个函数在它的子类里面可以被重载,这样的话,编译器就可以使用后期绑定来达到多态了,也就是:用基类的指针来调用子类的这个函数。
要实现虚函数必须保证派生类的函数名与基类相同,参数名参数类型等也要与基类相同。但派生类中的virtual关键字可以省略,也表示这是一个虚函数。