实验4
任务2:
#include <iostream> #include <typeinfo> class Graph { public: virtual void draw() { std::cout << "Graph::draw() : just as an interface\n"; } }; class Rectangle : public Graph { public: void draw() { std::cout << "Rectangle::draw(): programs of draw a rectangle\n"; } }; class Circle: public Graph { public: void draw() { std::cout << "Circle::draw(): programs of draw a circle\n"; } }; void fun(Graph* ptr) { std::cout << "pointer type: " << typeid(ptr).name() << "\n"; std::cout << "RTTI type: " << typeid(*ptr).name() << "\n"; ptr->draw(); } int main() { Graph g1; Rectangle r1; Circle c1; g1.draw(); r1.draw(); c1.draw(); std::cout << "\n"; r1.Graph::draw(); c1.Graph::draw(); std::cout << "\n"; fun(&g1); fun(&r1); fun(&c1); }
图片演示:
修改后运行图:
同名覆盖原则:
我的理解是当基类与派生类有同名成员时,若基类没用virtual声明为虚基类,则基类同名成员被覆盖,否则称为重写。
作用域分辨符:
若在基类被覆盖的情况下仍要访问,则可以通过类名::成员名这种方式访问。
类型兼容原则:
简单来说就是基类对象可以用公有派生类代替(隐式的转换),但只能使用从基类继承来的成员。
任务3:
battery.hpp:
#include<iostream> class battery { private: int capacity; public: battery(int _capacity = 70) :capacity(_capacity) {}; ~battery() { }; int get_capacity() { return capacity; } };
car.hpp:
#ifndef CAR_HPP #define CAR_HPP #include<iostream> #include<string> using namespace std; class car { private: string maker; string model; int year; int odometers; public: car(string _maker = "china", string _model = "zero", int _year = 0, int _odometers = 0) :maker(_maker), model(_model), year(_year),odometers(_odometers) {}; void info() const; int show_odometers() { return odometers; }; void update_odometers(int I); ~car() { }; }; void car::info() const { cout << "maker:" << maker << endl; cout << "model" << model << endl; cout << "year" << year << endl; cout << "odometers" << odometers << endl; } void car::update_odometers(int I) { car p1; odometers += I; if (odometers < p1.show_odometers()) cout << "the information is wrong" << endl; else cout << "odometers" << odometers; } #endif
electriccar.hpp:
#include <iostream> #include "car.hpp" #include "battery.hpp" using namespace std; class ElectricCar : public car,public battery { private: battery p1; public: ElectricCar(string _maker = "china", string _model = "zero", int _year = 0, int _odometers = 0, battery _p1 = 70); void info(); }; ElectricCar::ElectricCar(string _maker , string _model , int _year, int _odometers, battery _p1 ) :car(_maker, _model, _year), battery(_p1) { }; void ElectricCar :: info() { car::info(); cout << "battery:" << p1.get_capacity() << endl; }
task3.cpp:
#include "electricCar.hpp" int main() { using namespace std; // test class of Car car oldcar("Audi", "a4", 2016); cout << "--------oldcar's info--------" << endl; oldcar.update_odometers(25000); oldcar.info(); cout << endl; // test class of ElectricCar ElectricCar newcar("Tesla", "model s", 2016); newcar.update_odometers(2500); cout << "\n--------newcar's info--------\n"; newcar.info(); }
运行效果图:
任务4:
pets.hpp
#pragma once #ifndef MACHINEPETS_H #define MACHINEPETS_H #include<iostream> #include <string> using namespace std; class MachinePets { private: string nickname; public: MachinePets(const string s = "bamax") :nickname(s) {}; string get_nickname() const { return nickname; }; virtual string talk() { return "dododo"; }; }; class Petcats: public MachinePets { public: Petcats(const string s) : MachinePets(s) {}; virtual string talk() { return "miaomiaomiao"; }; }; class PetDogs:public MachinePets { public: PetDogs(const string s) :MachinePets(s) {}; virtual string talk() { return "wangwangwang"; }; }; #endif
task.cpp:
#include <iostream> #include "pets.h" void play(MachinePets* ptr) { std::cout << ptr->get_nickname() << " says " << ptr->talk() << std::endl; } int main() { Petcats cat("miku"); PetDogs dog("da huang"); play(&cat); play(&dog); }
运行图:
对虚函数的理解: 通过指针调用不同层次的同名函数来实现同名函数的区别调用