关于#C++多态与虚函数#的问题,如何解决?


#include<iostream>
using namespace std;
//C++的多态与虚函数 
//基类Point
class Point {
    public:
        Point(int xa, int yb) { //有参构造函数
            x = xa;
            y = yb;
        }A
        Point(){
            x = 0;
            y = 0;
        } 
        //定义虚函数display(),满足子类继承时的多态效应。
        //补全代码 
        



        //----------------------------------------------------
        //由于在Point基类阶段,无法实现实际的求面积方法,因此将get_area()设计为纯虚函数。
        //请补全代码 
        
        

        //------------------------------------------------
        //析构函数通常定义为虚函数
        //请补全析构函数头 
        
        
        //--------------------------------
        {
            cout << "Point destructor" << endl;
        }
    protected:
        int x;  //x坐标
        int y;  //y坐标
};
//Square继承了Point 
class Square : public Point{
    public:
        Square(int xa, int xb, int len):Point(xa,xb),length(len){
        }
        Square()
        {
            length = 1;
        }
        void display(){
            //显示一个方形
            cout<<"调用Square的display函数,显示一个正方形.\n"<< "坐标:(" << x << ", " << y << "), 边长:" << length <<endl;
        }
        //补全代码,实现自己的求面积函数get_area 
        
        

        //-------------------------------------- 
        //析构函数通常定义为虚函数
        //请补全析构函数头 
        
        
        //-------------------------------------- 
        {
            cout << "Square destructor" << endl;
        }
    protected:
        int length;
};
//Circle继承了Point 
class Circle: public Point {
    public:
        Circle(int xa, int xb, int r):Point(xa,xb) {
            radius = r;
        }
        Circle(){
            radius = 1;
        }
        void display() { //显示一个圆
            cout<<"调用Circle的display函数,显示一个圆.\n"<< "坐标:(" << x << ", " << y << "), 半径:" << radius <<endl;
        }
        //补全代码,实现自己的求面积函数get_area
        
        

        //------------------------------------------
        //析构函数通常定义为虚函数
        //请补全析构函数头 
        
        

        //----------------------------------------------- 
        {
            cout << "Circle destructor" << endl;
        }
    protected:
        int radius;
};

//编写一个Triangle类,继承Point,属性包含底边长和高
//并有自己的有参,无参构造函数,display函数和get_area函数,以及析构函数 
//此处补全代码: 













//--------------------------------------------------------------- 

//显示一个图形的通用函数Disp
void Disp(/*补全代码,填上参数,仔细思考这里应该填写什么类型的 对象?引用?指针?*/)
{
    p.display();
}
//显示一个图形面积的通用函数:Area_of_shape 
void Area_of_shape(/*补全代码,填上参数,仔细思考这里应该填写什么类型的 对象?引用?指针?*/)
{
    cout << s->get_area() << endl;
}
//函数create_shapes实现在堆内存中,动态生成一组图形,并返回首地址。
//option表示图形类型,1为方形,2为圆形,3为三角形 
//num为生成图形的数量 
Point* create_shapes(int option, int num)
{
    //补全代码,实现功能 
    //建议使用switch,并注意new对象数组的用法。
    
    //--------------------------------------------    
} 
int main() {
    //在堆内存中生成不同的图形。
    //定义基类图形指针
    Point *p; 
    int num;//个数 
    //输入即将生成的方形个数
    cin >> num;
    //生成一组方形 
    p = create_shapes(1, num);
    //依次显示这组方形的基本信息,以及面积。 
    for(int i = 0; i < num; i++)
    {
        
        //注意:p作为基类指针,在指向子类数组时,
        //其对于属性的作用范围仍局限在子类中的基类属性。
        //若直接通过+i或[i]形式,会造成内存指向的错位。
        //因此,需要想办法将其强制转换为子类类型的指针。
        //下同 
        //显示基本信息
        Disp(/*补全代码,填写实参*/);
        //显示面积值
        Area_of_shape(/*补全代码,填写实参*/); 
        
    }
    //注销
    //注意,由于涉及到数组的注销,因此注销时,基类指针,也需要转换为子类指针才能顺利注销,下同。 
    //请补齐注销代码 
    
    
    //--------------------------------
    //输入即将生成的圆形个数
    cin >> num;
    //生成一组圆形 
    p = create_shapes(2, num);
    //依次显示这组圆形的基本信息,以及面积。 
    for(int i = 0; i < num; i++)
    {
        Disp(/*补全代码,填写实参*/);
        Area_of_shape(/*补全代码,填写实参*/); 
    }
    //注销 
    //请补齐注销代码 
    
    
    //-------------------------------- 
    //输入即将生成的三角形个数
    cin >> num;
    //生成一组三角形 
    p = create_shapes(3, num);
    //依次显示这组三角形的基本信息,以及面积。 
    for(int i = 0; i < num; i++)
    {
        Disp(/*补全代码,填写实参*/);
        Area_of_shape(/*补全代码,填写实参*/); 
    }
    //注销 
    //请补齐注销代码 
    
    
    //---------------------------------------------------- 
    return 0;
}

基于new bing的编写参考:
定义虚函数display和纯虚函数get_area,具体内容由子类去实现。

class Point {
public:
    Point(int xa, int yb) { // 有参构造函数
        x = xa;
        y = yb;
    }
    Point() {
        x = 0;
        y = 0;
    }
    virtual void display() {
        cout << "调用Point的display函数,显示一个点。" << endl;
    }
    virtual double get_area() = 0; // 纯虚函数,由子类去实现
    virtual ~Point() {
        cout << "Point destructor" << endl;
    }
protected:
    int x;  // x坐标
    int y;  // y坐标
};

在Square和Circle类中分别实现display和get_area函数,并在析构函数中输出提示信息。

class Square : public Point {
public:
    Square(int xa, int xb, int len):Point(xa, xb), length(len) {}
    Square() {
        length = 1;
    }
    void display() {
        cout << "调用Square的display函数,显示一个正方形。" << endl;
        cout << "坐标:(" << x << ", " << y << "), 边长:" << length << endl;
    }
    double get_area() {
        return length * length;
    }
    ~Square() {
        cout << "Square destructor" << endl;
    }
private:
    int length;
};

class Circle: public Point {
public:
    Circle(int xa, int xb, int r):Point(xa, xb), radius(r) {}
    Circle() {
        radius = 1;
    }
    void display() {
        cout << "调用Circle的display函数,显示一个圆。" << endl;
        cout << "坐标:(" << x << ", " << y << "), 半径:" << radius << endl;
    }
    double get_area() {
        return 3.14 * radius * radius;
    }
    ~Circle() {
        cout << "Circle destructor" << endl;
    }
private:
    int radius;
};


添加Triangle类,与Square和Circle类类似,实现display和get_area函数,并在析构函数中输出提示信息。


class Triangle : public Point {
public:
    Triangle(int xa, int xb, int base, int height):Point(xa, xb), base(base), height(height){}
    Triangle(){
        base = 1;
        height = 1;
    }
    void display(){
        cout << "调用Triangle的display函数,显示一个三角形。" << endl;
        cout << "坐标:(" << x << ", " << y << "), 底边长:" << base << ", 高:" << height << endl;
    }
    double get_area(){
        return 0.5 * base * height;
    }
    ~Triangle(){
        cout << "Triangle destructor" << endl;
    }
private:
    int base; // 底边长
    int height; // 高
};

在create_shapes函数中使用switch语句和new对象数组来动态生成一组图形,并返回指向该数组的首地址的基类指针。

Point* create_shapes(int option, int num) {
    switch (option) {
        case 1: {
            Square* squares = new Square[num];
            return squares;
            break;
        }
        case 2: {
            Circle* circles = new Circle[num];
            return circles;
            break;
        }
        case 3: {
            Triangle* triangles = new Triangle[num];
            return triangles;
            break;
        }
        default:
            return nullptr;
            break;
    }
}

在main函数中,先生成一组方形并依次显示其属性和面积,然后注销该组方形,再生成一组圆形和一组三角形进行同样的操作。

int main() {
    // 在堆内存中生成不同的图形。
    // 定义基类图形指针
    Point *p;
    int num; // 个数

    // 生成一组方形
    cout << "请输入即将生成的方形个数:";
    cin >> num;
    p = create_shapes(1, num);
    for(int i = 0; i < num; i++) {
        Square* sq = dynamic_cast<Square*>(p + i);
        if (sq) {
            sq->display();
            cout << "面积:" << sq->get_area() << endl;
        }
    }
    delete[] p;
    cout << endl;

    // 生成一组圆形
    cout << "请输入即将生成的圆形个数:";
    cin >> num;
    p = create_shapes(2, num);
    for(int i = 0; i < num; i++) {
        Circle* c = dynamic_cast<Circle*>(p + i);
        if (c) {
            c->display();
            cout << "面积:" << c->get_area() << endl;
        }
    }
    delete[] p;
    cout << endl;

    // 生成一组三角形
    cout << "请输入即将生成的三角形个数:";
    cin >> num;
    p = create_shapes(3, num);
    for(int i = 0; i < num; i++) {
        Triangle* t = dynamic_cast<Triangle*>(p + i);
        if (t) {
            t->display();
            cout << "面积:" << t->get_area() << endl;
        }
    }
    delete[] p;

    return 0;
}

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7782248
  • 这篇博客你也可以参考下:C ++头文件的十大错误,如何解决这些问题
  • 除此之外, 这篇博客: C++基础知识中的 虚函数的作用? 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 虚函数用于实现多态
    但是虚函数在设计上还具有封装和抽象的作用。比如抽象工厂模式。

  • 您还可以看一下 夏浡源老师的C++入门基础视频精讲课程中的 函数的递归调用小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    多态和虚函数是C++中重要的特性之一,可以大大提高代码的可维护性和拓展性。如果你已经掌握了基本的C++语法,那么接下来可以开始学习多态和虚函数。

    多态指的是同一个类的不同实例或者不同类之间的同名函数,可以根据调用的对象自动判断应该调用哪个函数,从而大大简化了代码的重用和扩展。

    虚函数是实现多态的关键,可以通过定义一个基类,并让基类的某个成员函数为虚函数,从而让派生类对这个函数进行重写,实现多态特性。具体步骤如下:

    1. 定义基类和派生类

    首先我们需要定义一个基类,其中包含一个虚函数:

    class Figure {
    public:
        virtual float area() = 0;
    };
    

    然后我们定义一个派生类Rectangle,并重写虚函数area:

    class Rectangle : public Figure {
    public:
        float area() {
            cout << "Rectangle area" << endl;
            return 10.0;
        }
    };
    

    同理,我们还可以定义其它的派生类,例如Circle:

    class Circle : public Figure {
    public:
        float area() {
            cout << "Circle area" << endl;
            return 3.14;
        }
    };
    
    1. 在主函数中进行调用

    在主函数中,我们可以定义Figure指针,并根据需要指向Rectangle或者Circle实例,然后调用虚函数area,实现多态特性:

    int main() {
        Figure* ptr;
        Rectangle rec;
        Circle cir;
    
        ptr = &rec;
        ptr->area();
    
        ptr = &cir;
        ptr->area();
    
        return 0;
    }
    

    最后输出结果如下:

    Rectangle area
    Circle area
    

    可以看到,当Figure指针ptr分别指向Rectangle和Circle时,调用的是不同的函数,实现了多态特性。

    总结一下,实现多态和虚函数需要以下几个步骤:

    1. 定义基类,并定义一个虚函数。
    2. 定义派生类,并重写虚函数。
    3. 在主函数中使用指针指向不同的实例,并调用虚函数,实现多态特性。

    如果你对多态和虚函数还有疑问,可以多看看相关的教程和例子,不断练习和测试。