实例(Animal)介绍面向对象编程之继承和多态性(C++版)

实例(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;

}

四、代码运行展示
在这里插入图片描述

原创文章 11 获赞 274 访问量 4887

猜你喜欢

转载自blog.csdn.net/m0_46518461/article/details/105840516