学习目的
- 掌握派生类的定义和使用;
- 掌握派生类构造与析构函数的定义;
- 掌握重写基类的成员函数;
- 掌握通过基类指针或引用实现多态的方法。
5.2 实习任务
5.2.1 实习任务一
现要定义处理 3 维点的类,而又不能直接修改 Point 类,以 Point 类作为基
类派生得到 Point3D,Point3D 的定义和部分功能已经实现,请补充未完成的部
分成员函数。要求构造函数通过初始化列表实现。
在 Point3D 的 getDistance 方法中,通过调用基类的 getDistance 可 以计算出 XY 平面内的距离 dis,再通过 sqrt(disdis+dzdz)即可计算出 3D 空间 内点的距离。
#include <iostream>
#include <cmath>
using namespace std;
class Point{
public:
Point():x(0), y(0){}//初始化列表
Point(double newX, double newY){
setValue(newX, newY);
}
Point(const Point &p){
setValue(p.getX(), p.getY());
}
//~Point();
void setValue(double newX, double newY){
x = newX;
y = newY;
}
double getX()const{return x;}
double getY()const{return y;}
double getDistance(const Point &p2)const{
return sqrt(pow(x-p2.getX(),2)+pow(y-p2.getY(),2));
}
friend double getDistance(const Point &p1, const Point &p2){
return sqrt(pow(p1.getX()-p2.getX(),2)+pow(p1.getY()-p2.getY(),2));
}
private:
double x,y;
};
class Point3D : public Point{
public:
Point3D(double newX=0, double newY=0, double newZ=0):Point(newX, newY){z = newZ;}
double getZ() const{return z;}
double getDistance( const Point3D& p)const{
return sqrt(pow(this->Point::getDistance(p),2)+pow(z-p.z,2));
}
private:
double z;
};
int main()
{
// Point p1(3,4);
// Point p2(5,2);
// double distance = p1.getDistance(p2);
// cout<<"Distance:"<<distance<<endl;
// distance = getDistance(p1,p2);
// cout<<"Distance:"<<distance<<endl;
Point p1(3, 4), p2(5,3);
Point3D p1_3D(3,4,6);
Point3D p2_3D(2,6,9);
double dis=p1.getDistance(p2); //计算二维点 p1 和 p2 的距离
cout<<"Distance between p1 and p2: "<<dis<<endl;
dis=p1_3D.getDistance(p2_3D); //计算 3 维点 p1_3D 和 p2_3D 的距离
cout<<"Distance between p1_3D and p2_3D: "<<dis<<endl;
return 0;
}
运行结果:
Distance between p1 and p2: 2.23607
Distance between p1_3D and p2_3D: 3.74166
[Finished in 0.3s]
修改程序
dis=p2.getDistance(p2_3D); //计算点 p1_3D 和 p2 的距离
cout<<"Distance between p1_3D and p2: "<<dis<<endl;
Distance between p1_3D and p2: 4.24264
运行成功!
修改程序
dis=p1_3D.getDistance(p2); //计算点 p1_3D 和 p2 的距离
cout<<"Distance between p1_3D and p2: "<<dis<<endl;
报错
no viable conversion from 'Point' to 'const Point3D'
【 提示】如果某个函数调用需要传递基类对象,可以将派生类对象传递给他, 此时将发生切片效果,只将基类需要的数据复制过去。相反,如果需要 1 个派生类对象,传递基类对象将无法通过编译。
增加构造函数
Point3D(const Point&p):Point(p),z(0){}
运行成功
Distance between p1_3D and p2: 6.40312
【提示】只含有 1 个参数的构造函数称为类型转换构造函数,可以将传入参数类型转换为当前类类型。如果需要将基类对象复制给派生类对象,可以通过类型转换构造函数间接实现。
5.2.2 实习任务二
#include <iostream>
#include <cmath>
using namespace std;
const double PI = 3.14;
class Shape{
public:
// double virtual getArea()const{
// return 0;
// }
double virtual getArea()const=0;
// double virtual getPerimeter()const{
// return 0;
// }
double virtual getPerimeter()const=0;
};
class Circle: public Shape{
public:
Circle(double r): radius(r){}
double getArea() const;
double getPerimeter() const;
private:
double radius;
};
double Circle::getArea()const{
return PI*radius*radius;
}
double Circle::getPerimeter()const{
return 2*PI*radius;
}
class Rectangle: public Shape{
public:
Rectangle(double w, double h): width(w), height(h){}
double getArea() const;
double getPerimeter() const;
private:
double width;
double height;
};
double Rectangle::getArea()const{
return width*height;
}
double Rectangle::getPerimeter()const{
return 2*(width + height);
}
class Triangle: public Shape{
public:
Triangle(double newA, double newB, double newC):a(newA),b(newB),c(newC){}
double getArea()const;
double getPerimeter()const;
private:
double a,b,c;
};
double Triangle::getArea()const{
double p = this->getPerimeter() / 2.0;//p是半周长,这个别搞错了
return sqrt(p*(p-a)*(p-b)*(p-c));
}
double Triangle::getPerimeter()const{
return a+b+c;
}
void outputInfo(const Shape&sh);
void outputInfo(const Shape& sh){
cout<<"Area:"<<sh.getArea()<<endl;
cout<<"Perimeter:"<<sh.getPerimeter()<<endl;
}
int main(){
//Shape shape0;
Rectangle shape1(3,4);
Circle shape2(1.0);
Triangle shape3(3,4,5);
shape3.getArea();
// outputInfo(shape0);
outputInfo(shape1);
outputInfo(shape2);
outputInfo(shape3);
return 0;
}
运行结果:
Area:12
Perimeter:14
Area:3.14
Perimeter:6.28
Area:6
Perimeter:12
[Finished in 0.3s]
课后练习
#include <iostream>
using namespace std;
class Base{
public:
void display(){cout<<"Base display"<<endl;}
};
class Derived: public Base{
public:
void display(){cout<<"Derived display"<<endl;}
};
void display(Base & rr){
rr.display();
}
int main(){
Base b;
Derived d;
display(b);
display(d);
return 0;
}
运行结果:
Base display
Base display
[Finished in 0.3s]
另:
void display(Derived & rr){
rr.display();
}
int main(){
Base b;
Derived d;
b = d;// d = b报错
// display(b);
display(d);
return 0;
}
Derived display
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Person{
public:
Person(){
cout<<"Person constructed!"<<endl;
}
~Person(){
cout<<"Person destructed!"<<endl;
}
};
class Student: public Person{
public:
Student(){cout<<"Student constructed!"<<endl;}
~Student(){cout<<"Student destructed"<<endl;}
};
class Teacher: public Person{
public:
Teacher(){
cout<<"Teacher constructed!"<<endl;
}
~Teacher(){
cout<<"Teacher destructed!"<<endl;
}
};
int main(){
Student s;
Teacher t;
return 0;
}
因缺思婷 results ↓
运行结果:
Person constructed!
Student constructed!
Person constructed!
Teacher constructed!
Teacher destructed!
Person destructed!
Student destructed
Person destructed!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Animal{
public:
virtual void Report(){cout<<"Report from Animal!"<<endl;}
};
class Tiger: public Animal{
public:
virtual void Report(){cout<<"Report from Tiger!"<<endl;}
};
class Monkey: public Animal{
public:
virtual void Report(){
cout<<"Report from Monkey!"<<endl;
}
};
void show(Animal *p){
p->Report();
}
int main(){
Tiger tiger;
Monkey monkey;
Animal animal = tiger;
show(&tiger);
show(&monkey);
show(&animal);
return 0;
}
运行结果:
Report from Tiger!
Report from Monkey!
Report from Animal!
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Base{
private:
int base;
public:
Base(int b){
base = b;
cout<<"base = "<<b<<endl;
}
~Base(){}
};
class Derived: public Base{ //按照base->derived的顺序赋值
private:
Base bb;
int derived;
public:
Derived(int d, int b, int c):bb(c),Base(b){
derived = d;
cout<<"derived = "<<derived<<endl;
}
~Derived(){}
};
int main(){
Derived d(3,4,5);
return 0;
}
运行结果:
base = 4
base = 5
derived = 3
[Finished in 0.3s]
#include <iostream>
using namespace std;
class Base{
public:
Base (int i,int j){ x0=i; y0=j;}
void Move(int x,int y){ x0+=x; y0+=y;}
void Show(){ cout<<"Base("<<x0<<","<<y0<<")"<<endl;}
private:
int x0,y0;
};
class Derived: private Base{
public:
Derived(int i,int j,int m,int n):Base(i,j){ x=m; y=n;}
void Show (){cout<<"Next("<<x<<","<<y<<")"<<endl;}
void Move1(){Move(2,3);}
void Show1(){Base::Show();}
private:
int x,y;
};
int main( ){
Base b(1,2);
b.Show();
Derived d(3,4,10,15);
d.Move1();
d.Show();
d.Show1();
return 0;
}
Base(1,2)
Next(10,15)
Base(5,7)
[Finished in 0.3s]
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Sales{
private:
string product;
double price;
double quantity;
public:
Sales(string prod,double p,double q):product(prod),price(p),quantity(q){}
virtual double net_price()const{return price*quantity;}
};
class DiscountSales:public Sales{
private:
double rate;
public:
DiscountSales(string prod,double p,double q,double r) :Sales(prod,p,q),rate(r){}
virtual double net_price()const{return Sales::net_price()*rate;}
};
class FullDiscountSales:public Sales{
private:
double fullMoney,discountMoney;
public:
FullDiscountSales(string prod,double p,double q,double f,double d) :Sales(prod,p,q),fullMoney(f),discountMoney(d){}
virtual double net_price()const{
double money=Sales::net_price();
int count=0;
while((money-=fullMoney)>=0) {count++;}
return Sales::net_price()-count*discountMoney;
}
};
int main(){
vector< Sales* > vec;
vec.push_back(new DiscountSales("C++",100,2,0.8));
vec.push_back(new FullDiscountSales("Java",80,5,200,30));
cout<<vec[0]->net_price()<<endl;
cout<<vec[1]->net_price()<<endl;
double totalPrice=0;
for(auto p : vec) totalPrice+=p->net_price();
cout<<"totalPrice:"<<totalPrice<<endl;
for(auto p: vec) delete p;
return 0;
}
运行结果:
160
340
totalPrice:500
[Finished in 0.4s]