实验四:继承
任务二:
1、
cpp:
#include <iostream> #include <typeinfo> // definitation of Graph class Graph { public: void draw() { std::cout << "Graph::draw() : just as an interface\n"; } }; // definition of Rectangle, derived from Graph class Rectangle : public Graph { public: void draw() { std::cout << "Rectangle::draw(): programs of draw arectangle\n"; } }; // definition of Circle, derived from Graph class Circle : public Graph { public: void draw() { std::cout << "Circle::draw(): programs of draw acircle\n"; } }; // definitaion of fun(): as a call interface void fun(Graph *ptr) { std::cout << "pointer type: " << typeid(ptr).name() << "\n"; std::cout << "RTTI type: " << typeid(*ptr).name() << "\n"; ptr -> draw(); } // test int main() { Graph g1; Rectangle r1; Circle c1; // call by object name g1.draw(); r1.draw(); c1.draw(); std::cout << "\n"; // call by object name, and using the scope resolution operator:: r1.Graph::draw(); c1.Graph::draw(); std::cout << "\n"; // call by pointer to Base class fun(&g1); fun(&r1); fun(&c1); }
运行结果:
2、
cpp:
#include <iostream> #include <typeinfo> // definitation of Graph class Graph { public: virtual void draw() { std::cout << "Graph::draw() : just as an interface\n"; } }; // definition of Rectangle, derived from Graph class Rectangle : public Graph { public: void draw() { std::cout << "Rectangle::draw(): programs of draw arectangle\n"; } }; // definition of Circle, derived from Graph class Circle : public Graph { public: void draw() { std::cout << "Circle::draw(): programs of draw acircle\n"; } }; // definitaion of fun(): as a call interface void fun(Graph *ptr) { std::cout << "pointer type: " << typeid(ptr).name() << "\n"; std::cout << "RTTI type: " << typeid(*ptr).name() << "\n"; ptr -> draw(); } // test int main() { Graph g1; Rectangle r1; Circle c1; // call by object name g1.draw(); r1.draw(); c1.draw(); std::cout << "\n"; // call by object name, and using the scope resolution operator:: r1.Graph::draw(); c1.Graph::draw(); std::cout << "\n"; // call by pointer to Base class fun(&g1); fun(&r1); fun(&c1); }
运行结果:
任务三:
car.hpp:
#include<iostream> #include<string> using namespace std; class Car { private: string maker,model;int year,odometers; public:Car(string x="UNKNOW",string y="UNKNOW",int x1=1000,int y1=0):maker(x),model(y),year(x1),odometers(y1){}; void info() { cout<<"maker:\t"<<maker<<endl; cout<<"model:\t"<<model<<endl; cout<<"year:\t"<<year<<endl; cout<<"odometers:\t"<<odometers<<endl; } void update_odometers(int t) { if(t<odometers) cout<<"data is wrong,please update again\n"; else odometers=t; } };
battery.hpp:
#include<iostream> #include<string> using namespace std; class Battery { private: string capacity; public: Battery(string x="70-kWh"):capacity(x){}; string get_capacity(){return capacity;}; };
electriccar.hpp:
#include<iostream> #include<string> #include"battery.hpp" #include"car.hpp" using namespace std; class ElectricCar:public Car { private:Battery battery; public:ElectricCar(string x="UNKNOW",string y="UNKNOW",int x1=1000,int y1=0,string t="70-kWh"):battery(t),Car(x,y,x1,y1){}; void info() { Car::info(); cout<<"capacity:\t"<<battery.get_capacity()<<endl; } };
task3.cpp:
#include <iostream> #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(); }
运行结果:
任务四:
pets.hpp:
#include<iostream> #include<string> using namespace std; class MachinePets { private:string nickname; public:MachinePets(const string s):nickname(s){}; virtual string talk(){return "?";}; string get_nickname(){return nickname;}; }; class PetCats:public MachinePets { public:PetCats(const string s):MachinePets(s){}; string talk(){return "cant become human";}; }; class PetDogs:public MachinePets { public:PetDogs(const string s):MachinePets(s){}; string talk(){return "failure dog";}; };
task4.cpp:
#include <iostream> #include "pets.hpp" 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); }
运行结果:
总结:
任务二:
同名覆盖原则:派生类与基类中有相同成员时,通过派生类对象使用的是派生类的同名成员;
二元作用域分辨符:类名称::成员名,可以精确指定某个成员;
类型兼容原则:在需要基类对象的任何地方都可以使用公有派生类的对象来替代:
(1)派生类对象可以隐含转化为基类对象,b1=d1;
(2)派生类的对象可以初始化基类的引用,B &rb=d1;
(3)派生类的指针可以隐含转化为基类的指针,pb1=&d1;
对于某个基类的多次引用,我们更推荐用virtual定义,这样可以让每个派生类对于同一函数拥有不同空间,更便于管理,避免基类中的某些函数在引用过程中不会产生歧义报错
任务三是很普通的类的定义,主要加强了对继承的应用
任务四就是对任务二的理解,virtual使得两个派生类都能够返回自己定义函数值