- 动态绑定:
c++中,我们在使用基类的引用(指针)调用虚函数时,就会发生动态绑定。所谓动态绑定,就是在运行时,虚函数会根据绑定对象的实际类型,选择调用函数的版本。 - 动态多态
动态多态是利用虚函数实现的。在类中如果出现virtual关键字,那么这个类的大小将会多出一个指针的大小(32位4字节,64位8字节),多出来的这个指针(_vfptf)指向函数指针数组的首地址,我们称这个函数指针数组为虚函数表。
子类在继承基类时,会连同虚函数表一起继承,如果重写基类的虚函数,则会覆盖掉虚函数表中的函数地址,这就是可以调用子类对象方法的根本原因。例如 (B类继承之A类)a=&b; 此时基类指针a指向了子类对象b的虚函数表的首地址,通过解引用就可以调用子类b中的重写的方法了。(这里解释一下,虚函数表相对于成员变量是排在前面的,所以&b的地址指向虚函数表的首地址)。
多态的实现:1 父类要有虚函数
2 子类继承父类,并要对虚函数重写
3 要有父类指针(父类引用)指向子类对象
#pragma once #include// Predicts the weather using proven new-age techniques given the current // temperature and the distance from Jupiter to Mars. If these values are // not provided, a guess is still given but it's only 99% accurate. class WeatherPrediction { public: // Virtual destructor virtual ~WeatherPrediction(); // Sets the current temperature in Fahrenheit virtual void setCurrentTempFahrenheit(int temp); // Sets the current distance between Jupiter and Mars virtual void setPositionOfJupiter(int distanceFromMars); // Gets the prediction for tomorrow's temperature virtual int getTomorrowTempFahrenheit() const; // Gets the probability of rain tomorrow. 1 means // definite rain. 0 means no chance of rain. virtual double getChanceOfRain() const; // Displays the result to the user in this format: // Result: x.xx chance. Temp. xx virtual void showResult() const; // Returns a string representation of the temperature virtual std::string getTemperature() const; private: int mCurrentTempFahrenheit; int mDistanceFromMars; };
#include#include #include "WeatherPrediction.h" using namespace std; WeatherPrediction::~WeatherPrediction() = default; void WeatherPrediction::setCurrentTempFahrenheit(int temp) { mCurrentTempFahrenheit = temp; } void WeatherPrediction::setPositionOfJupiter(int distanceFromMars) { mDistanceFromMars = distanceFromMars; } int WeatherPrediction::getTomorrowTempFahrenheit() const { // Obviously, this is nonsense return (mDistanceFromMars / 1000) + mCurrentTempFahrenheit; } double WeatherPrediction::getChanceOfRain() const { // Obviously, this is nonsense too return 0.5; } void WeatherPrediction::showResult() const { cout << "Result: " << (getChanceOfRain() * 100) << " chance." << " Temp. " << getTomorrowTempFahrenheit() << endl; } std::string WeatherPrediction::getTemperature() const { stringstream ss; ss << mCurrentTempFahrenheit; return ss.str(); }
#pragma once
#include "WeatherPrediction.h"
class MyWeatherPrediction : public WeatherPrediction
{
public:
virtual void setCurrentTempCelsius(int temp);
virtual int getTomorrowTempCelsius() const;
virtual void showResult() const override;
virtual std::string getTemperature() const override;
private:
static int convertCelsiusToFahrenheit(int celsius);
static int convertFahrenheitToCelsius(int fahrenheit);
};
#includetest#include "MyWeatherPrediction.h" using namespace std; void MyWeatherPrediction::setCurrentTempCelsius(int temp) { int fahrenheitTemp = convertCelsiusToFahrenheit(temp); setCurrentTempFahrenheit(fahrenheitTemp); } int MyWeatherPrediction::getTomorrowTempCelsius() const { int fahrenheitTemp = getTomorrowTempFahrenheit(); return convertFahrenheitToCelsius(fahrenheitTemp); } void MyWeatherPrediction::showResult() const { cout << "Tomorrow's temperature will be " << getTomorrowTempCelsius() << " degrees Celsius (" << getTomorrowTempFahrenheit() << " degrees Fahrenheit)" << endl; cout << "The chance of rain is " << (getChanceOfRain() * 100) << " percent" << endl; if (getChanceOfRain() > 0.5) { cout << "Bring an umbrella!" << endl; } } int MyWeatherPrediction::convertCelsiusToFahrenheit(int celsius) { return static_cast ((9.0 / 5.0) * celsius + 32); } int MyWeatherPrediction::convertFahrenheitToCelsius(int fahrenheit) { return static_cast ((5.0 / 9.0) * (fahrenheit - 32)); } string MyWeatherPrediction::getTemperature() const { // Add 癋 to the string. // Note: u00B0 is the ISO/IEC 10646 representation of the degree symbol. return WeatherPrediction::getTemperature() + "u00B0F"; }
#include#include "MyWeatherPrediction.h" using namespace std; int main() { MyWeatherPrediction p; p.setCurrentTempCelsius(33); p.setPositionOfJupiter(80); p.showResult(); cout << p.getTemperature() << endl; return 0; } out: Tomorrow's temperature will be 32 degrees Celsius (91 degrees Fahrenheit) The chance of rain is 50 percent 91°F



