源码如下,解释在后面。
#include <iostream>
using namespace std;
class B
{
public:
virtual void f1()
{
cout << "B:f1()" << endl;
}
virtual void f2()
{
cout << "B:f2()" << endl;
}
void g()
{
cout << "B:g()" << endl;
f1();
f2();
}
};
class D :public B
{
public:
virtual void f1()
{
cout << "D:f1()" << endl;
}
virtual void f3()
{
cout << "D:f3()" << endl;
}
void g()
{
cout << "D:g()" << endl;
f1();
f2();
}
};
int main()
{
D d;
D* pd = &d;
B* pb = &d;
B b = d;
b.f1();
b.f2();
b.g();
pb->f1();
pb->f2();
pb->g();
pd->f1();
pd->f2();
pd->f3();
pd->g();
}
对象直接调用自己的成员方法。
因为f1()方法增加了virtual关键字,d为D类的实例化对象,动态链接的方式查表,即使父类指针pb指向子类对象,依然调用子类D的实例化对象d的成员方法。
子类D中没有重写(覆盖)f2()方法,所以使用子类对象的成员方法。
g()方法前没有virtual,所以是静态链接,直接用指针类型B类内的方法,调用f1()时又因为f1()方法有virtural关键字,所以是动态链接,经过后期绑定后找到该指针指向对象的成员方法,打印出,D:f1(),
调用f2()方法时,基类没有f2(),所以使用继承自基类中的方法,java也同理。
删除掉程序内所有virtual关键字后运行结果如下
可以发现两者的结果没有不同,virtual的存在就是为了动态多态,动态链接存在的,但此时指针类型指向了它对应的对象类型,所以二者没有什么差异,方法优先使用自己的成员方法,若类内没有重写的方法,便使用继承的基类的方法。
观察结果,因为只没有f2()方法,所有调用基类的该方法,其他方法自动调用自己的。
要求
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const double PI = 3.1415926;
//图形的抽象基类
class Shape {
public:
virtual double Area() = 0; //求面积, 纯虚函数;
};
//求二维图形的抽象基类;
class Shape2D :public Shape {
public:
virtual double Perimeter() = 0; //求周长, 纯虚函数;
};
//求三维图形的抽象基类;
class Shape3D :public Shape {
public:
virtual double Volume() = 0; //求体积, 纯虚函数;
};
//派生类, 矩形;
class Rectangle : public Shape2D
{
public:
Rectangle(double length, double width) :length_(length), width_(width) {
}
double Area() {
return length_ * width_;
}
double Perimeter() {
return 2 * length_ + 2 * width_;
}
private:
double length_;
double width_;
};
//派生类, 椭圆;
class Ellipse :public Shape2D
{
public:
Ellipse(double semimajor, double semiminor) :semimajor_(semimajor), semiminor_(semiminor) {
}
double Area() {
return 2 * PI * semiminor_ + 4 * (semimajor_ - semiminor_);
}
double Perimeter() {
return PI * semimajor_ * semiminor_;
}
private:
double semimajor_;
double semiminor_;
};
//派生类, 圆;
class Circle : public Shape2D
{
public:
Circle(double radius) :radius_(radius) {
}
double Area() {
return PI * radius_ * radius_;
}
double Perimeter() {
return PI * 2 * radius_;
}
private:
double radius_;
};
//派生类, 球体;
class Sphere :public Shape3D
{
public:
Sphere(double radius) :radius_(radius) {
}
double Area() {
return 4 * PI * radius_ * radius_;
}
double Volume() {
return 4.0 / 3.0 * PI * radius_ * radius_ * radius_;
}
private:
double radius_;
};
//派生类, 圆柱体;
class Cylinder :public Shape3D
{
public:
Cylinder(double height, double radius) :height_(height), radius_(radius) {
}
double Area() {
return 2 * PI * radius_ * (height_ + radius_);
}
double Volume() {
return PI * radius_ * radius_ * height_;
}
private:
double height_;
double radius_;
};
//派生类, 圆锥体;
class Cone : public Shape3D
{
public:
Cone(double height, double radius) :height_(height), radius_(radius) {
}
double Area() {
return PI * radius_ * (radius_ + sqrt((height_ * height_) + (radius_ + radius_)), 2);
}
double Volume() {
return 1.0 / 3 * PI * radius_ * radius_ * height_;
}
private:
double height_;
double radius_;
};
class SumofShape
{
public:
//静态函数 计算图形数组面积之和
static double SumofArea(Shape* shape[], int n)
{
double sum = 0;
for (int i = 0; i < n; i++) {
sum += shape[i]->Area();
}
return sum;
}
//静态函数 计算图形数组周长之和
static double SumofPerimeter(Shape* shape[], int n)
{
double sum1 = 0;
for (int j = 0; j < n; j++) {
Shape2D* shape2d;
if (shape2d = dynamic_cast<Shape2D*>(shape[j])) {
sum1 += shape2d->Perimeter();
}
}
return sum1;
}
//静态函数 计算图形数组的体积之和
static double SumofVolume(Shape* shape[], int n)
{
double sum2 = 0;
for (int k = 0; k < n; k++) {
Shape3D* shape3d;
if (shape3d = dynamic_cast<Shape3D*>(shape[k]))
sum2 += shape3d->Volume();
}
return sum2;
}
private:
SumofShape() {
} //定义私有构造函数,禁止实例化
};
int main() {
Rectangle rectangle(2, 3);
Ellipse ellipse(8, 4);
Circle circle(3);
Sphere sphere(3);
Cylinder cylinder(3, 5);
Cone cone(3, 4);
Shape* shape_array[] = {
&rectangle, &ellipse, &circle, &sphere, &cylinder, &cone };
double sum_of_area = SumofShape::SumofArea(shape_array, 6);
double sum_of_perimeter = SumofShape::SumofPerimeter(shape_array, 6);
double sum_of_volume = SumofShape::SumofVolume(shape_array, 6);
cout << "面积总和:" << sum_of_area << "\n周长总和:" << sum_of_perimeter << "\n体积总和:" << sum_of_volume << endl;
return 0;
}