实验4 继承
task2:
原:
1 #include<iostream> 2 #include<typeinfo> 3 4 using namespace std; 5 6 class graph{ 7 public: 8 void draw(){ 9 cout << "graph::draw() : just as an interface" << endl; 10 } 11 }; 12 13 class rectangle : public graph{ 14 public: 15 void draw(){ 16 cout << "rectangle::draw(): programs of draw a rectangle\n" ; 17 } 18 }; 19 20 class circle : public graph{ 21 public: 22 void draw(){ 23 cout << "circle::draw(): programs of draw a circle" << endl; 24 } 25 }; 26 27 void fun(graph *ptr) 28 { 29 cout << "pointr type: " << typeid(ptr).name() << endl; 30 cout << "RTTI type: " << typeid(*ptr).name() << endl; // RTTI运行时类型识别 31 ptr -> draw(); //virtual使得能在子类中重写基类函数,基类中被重写的函数称作虚函数。 32 } 33 int main() 34 { 35 graph g1; 36 rectangle r1; 37 circle c1; 38 39 g1.draw(); 40 r1.draw(); 41 c1.draw(); 42 43 r1.graph::draw();//二元作用域分辨符 44 c1.graph::draw(); 45 46 cout << endl; 47 48 fun(&g1); 49 fun(&r1); 50 fun(&c1); 51 52 return 0; 53 }
改:
1 #include<iostream> 2 #include<typeinfo> 3 4 using namespace std; 5 6 class graph{ 7 public: 8 virtual void draw(){ 9 cout << "graph::draw() : just as an interface" << endl; 10 } 11 }; 12 13 class rectangle : public graph{ 14 public: 15 void draw(){ 16 cout << "rectangle::draw(): programs of draw a rectangle\n" ; 17 } 18 }; 19 20 class circle : public graph{ 21 public: 22 void draw(){ 23 cout << "circle::draw(): programs of draw a circle" << endl; 24 } 25 }; 26 27 void fun(graph *ptr) 28 { 29 cout << "pointr type: " << typeid(ptr).name() << endl; 30 cout << "RTTI type: " << typeid(*ptr).name() << endl; // RTTI运行时类型识别 31 ptr -> draw(); //virtual使得能在子类中重写基类函数,基类中被重写的函数称作虚函数。 32 } 33 int main() 34 { 35 graph g1; 36 rectangle r1; 37 circle c1; 38 39 g1.draw(); 40 r1.draw(); 41 c1.draw(); 42 43 r1.graph::draw();//二元作用域分辨符 44 c1.graph::draw(); 45 46 cout << endl; 47 48 fun(&g1); 49 fun(&r1); 50 fun(&c1); 51 52 return 0; 53 }
同名覆盖原则:
派生类与基类中有相同成员时,若未强行指名,则通过派生类对象使用的是派生类的同名成员;
如果要通过派生类的对象访问基类被覆盖的同名成员,需要加 对象名.基类名::同名成员 来限定。
二元作用域分辨符:
在派生类内部访问基类同名成员的语法形式:
基类名::数据成员名; 基类名::函数成员名(参数表);
如果是在派生类外通过派生类对象访问的话,前面还要加上“派生类对象名.”:
派生类对象名.基类名::数据成员名;
派生类对象名.基类名::函数成员名(参数表);
类型兼容原则:
类型兼容原则是指在需要基类对象的任何地方,都可以使用共有派生类的对象来替代。
(1) 派生类的对象可以赋值给基类对象
(2) 派生类的对象可以初始化基类的引用。
(3) 派生类对象的地址可以赋值给基类的指针。
task3:
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(); }
electrical.hpp:
#include<string> #include<iostream> #include"Battery.hpp" #include"car.hpp" class electriccar : public car{ public: electriccar(string n_maker, string n_model, int n_year, int n_battery = 70): car(n_maker, n_model, n_year), battery(n_battery){ //使用基类构造函数 odometers = 0; } void info() { car::info(); cout << "capacity: " << battery.get_capacity() << "-kwh" << endl; } private: Battery battery; };
car.hpp
#include<iomanip> #include<iostream> #include<string> using namespace std; class car{ public: car(string n_maker, string n_model, int n_year): maker(n_maker), model(n_model), year(n_year){ odometers = 0; } void info() { cout << "maker: " << maker << endl; cout << "model: " << model << endl; cout << "year: " << year << endl; cout << "odometers: " << odometers << endl; } void update_odometers(int x){ if(x < odometers){ cout << "Invalid input. Please check your info." << endl; }else odometers = x; } int odometers; private: string maker; string model; int year; };
Battery.hpp:
class Battery{ public: Battery(int n_capacity = 70):capacity(n_capacity){}; int get_capacity() { return capacity; } private: int capacity; };
task4:
#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); }
pets.hpp:
#include<string> using namespace std; class machinepets{ public: string nickname; machinepets(const string s):nickname(s){}; virtual string talk(){}; string get_nickname() const{ return nickname; } private: }; class petcats : public machinepets{ public: petcats(const string s): machinepets(s){}; string talk(){ return "miao wu~"; } }; class petdogs : public machinepets{ public: petdogs(const string s): machinepets(s){}; string talk(){ return "wang wang~"; } };