实例(Animal)介绍面向对象编程之继承和多态性(C++版)
一、面向对象编程之继承和多态性的特别注意之处总结(结合本实例进行的总结,所有解析代码均来自本实例):
1、抽象类中由至少一个纯虚函数,并且抽象类中的纯虚函数是不提供具体的实现,在继承类中如果用到抽象类中的纯虚函数要重新定义。如:
抽象类Animal中:
Animal.h中包含
virtual void setHeight( int ) = 0; //纯虚函数
在Animal.cpp中是不会给出virtual void setHeight( int ) = 0; 函数的具体实现
2、在抽象类中声明为虚函数,在继承类中将保持虚函数的性质,可以不写virtual关键字(好的编程习惯可以写上),如:
抽象类中:
virtual int getHeight() const;
继承类中可以这样写:
virtual int getHeight() const;
或
int getHeight() const;
3、virtual关键字只在接口函数中出现,在具体实现函数过程中不需要写,如:
接口函数:
virtual int getHeight() const;
具体实现函数:
int Animal::getHeight() const
{
return height;
} //前面不需要关键字virtual
4、实现多态性的两个重要点是
(1)、句柄要是基类的引用或基类的指针
(2)、所调用的函数是虚函数
如:
a->print(); //这里print函数必须声明为virtual
二、在完成本实例出现的问题及解决方法
1、首先是将基类中的get函数设置为纯virtual函数:
问题:在Animal.h中将所有get函数设置为virtual函数,在Animal.cpp中将不出现get函数的具体实现,如下:
//Animal.h
virtual int getHeight() const = 0;
//Animal.cpp 不出现以下:
int Animal::getHeight() const
{
return height;
}
那么在Dog.cpp将无法完成下列操作:
int Dog::getHeight() const
{
if ( useMetric( "height" ) )
return metricHeight;
else
return Animal::getHeight();
}
//第二个返回值出现问题
解决方法:将set函数设置为纯virtual函数
2、实例中继承类中set函数还有另一种实现方法,即返回引用,缺点是基类中的数据得不到安全保障,以其一为例:
int &Animal::getHeight() //返回引用,且不能用const限定
{
return height;
}
void Dog::setHeight( int h )
{
Animal::getHeight()= h;
}
三、完整的实例代码
// Debugging: Animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#include <string>
using std::string;
//定义Animal类作为抽象类(含至少一个纯虚函数)
class Animal
{
public:
Animal( int = 0, int = 0 ); //抽象类Animal构造函数
virtual void setHeight( int ) = 0; //setHeight函数,定义为纯虚函数,继承中使用到要重新写,抽象类中不提供具体函数实现
virtual int getHeight() const; //在测试函数中基类指针调用该函数,为实现多态性,这里需要设置成virtual函数
virtual void setWeight( int ) = 0; //setWeight函数,定义为纯虚函数,继承中使用到要重新写,抽象类中不提供具体函数实现
virtual int getWeight() const; //在测试函数中基类指针调用该函数,为实现多态性,这里需要设置成virtual函数
virtual void print() const ; //为实现多态性,这里需要设置成virtual函数
protected:
int height;
int weight;
};
#endif
// Debugging: Animal.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "Animal.h"
// default constructor
Animal::Animal( int h, int w )
{
height = h;
weight = w;
} // end class Animal constructor
// function print definition
void Animal::print() const
{
cout << "This animal's height and weight are as follows:\n"
<< "Height: " << height << "\tWeight: " << weight
<< endl << endl;
} // end function print
// return height
int Animal::getHeight() const
{
return height;
} // end function getHeight
// return weight
int Animal::getWeight() const
{
return weight;
} // end function getWeight
// Debugging: Dog.h
#ifndef DOG_H
#define DOG_H
#include "Animal.h"
class Dog : public Animal //派生类继承基类
{
public:
Dog( int = 0, int = 0, string = "Toto" );
virtual void print() const ; //
int getHeight() const;
int getWeight() const;
virtual void setHeight( int ) ; //重写纯虚函数
virtual void setWeight( int ) ;
string getName() const;
void setName( string );
private:
bool useMetric( string )const; //辅助函数
string name;
int metricHeight;
int metricWeight;
}; // end class Dog
#endif // DOG_H
// Debugging: Dog.cpp
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
#include "Dog.h"
Dog::Dog( int h, int w, string n )
: Animal( h, w )
{
setName( n );
metricHeight = h * 2.5;
metricWeight = w / 2.2;
}
string Dog::getName() const //返回name
{
return name;
}
void Dog::setName( string n )
{
name = n;
}
void Dog::print() const
{
cout << "This animal is a dog, its name is: "
<< name << endl;
Animal::print(); //调用基类的print函数
}
void Dog::setHeight( int h ) //重写setHeight函数
{
height= h;
}
void Dog::setWeight( int w ) //重写setWeight函数
{
weight= w;
}
int Dog::getHeight() const //返回height
{
if ( useMetric( "height" ) )
return metricHeight;
else
return Animal::getHeight();
}
int Dog::getWeight() const //返回weight
{
if ( useMetric( "weight" ) )
return metricWeight;
else
return Animal::getWeight();
}
bool Dog::useMetric( string type )const //工具函数,选择输出格式
{
int choice = 0;
cout << "Which units would you like to see the "
<< type << " in? (Enter 1 or 2)\n"
<< "\t1. metric\n"
<< "\t2. standard\n";
cin >> choice;
if ( choice == 1 )
return true;
else
return false;
}
// Debugging: Lion.h
#ifndef LION_H
#define LION_H
#include "Animal.h"
class Lion : public Animal
{
public:
Lion( int = 0, int = 0 );
virtual void setHeight( int ) ;
virtual void setWeight( int ) ;
virtual void print() const;
};
#endif
// Debugging: Lion.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "Lion.h"
Lion::Lion( int h, int w ) //默认构造函数
: Animal( h, w ) //成员初始化器初始化基类的数据成员
{
// 空的
}
void Lion::setHeight( int h )
{
height= h;
}
void Lion::setWeight( int w )
{
weight= w;
}
void Lion::print() const
{
cout << "This animal is a lion\n";
Animal::print();
}
// Debugging: Debugging.cpp
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
#include "Animal.h"
#include "Lion.h"
#include "Dog.h"
void setHeightWeight( Animal* ); //全局函数,参数是一个基类指针类型
int main()
{
Dog dog1( 60, 120, "Fido" ); //实例化对象dog1
Lion lion1( 45, 300 ); //实例化对象lion1
setHeightWeight( &lion1 );
setHeightWeight( &dog1 );
return 0;
}
void setHeightWeight( Animal* a )
{
int height;
int weight;
a->print();
cout << "Enter a new height (using standard units): ";
cin >> height;
a->setHeight( height );
cout << "Enter a new weight (using standard units): ";
cin >> weight;
a->setWeight( weight );
height = a->getHeight();
weight = a->getWeight();
cout << "Here are the new height and weight values:\n"
<< height << endl
<< weight << endl << endl;
}
四、代码运行展示