C++ 继承和虚函数

C++ inheritance and virtual funcions

这是我的任务:

设计classes Circle和Square继承自class Shape(包含所有形状共有的重心特征,为特定值和虚拟移动重心的函数函数周长、面积和读数)。 类应该有计算周长和面积的特定函数,以及读取数据成员的函数。

这是我所做的:

#include <iostream>

using namespace std;

class Point {
private:
    float x;
    float y;
public:
    Point();
    Point(float,float);
    ~Point();
};

Point::Point() {
}

Point::Point(float a,float b) {
    x=a;
    y=b;
}

Point::~Point() {
}

class Shape {
public:
    Shape(void);
    Shape(Point);
    virtual float circumference(void) {}
    virtual float area(void) {}
protected:
    Point center_of_gravity;
};

Shape::Shape(void) {
}

Shape::Shape(Point a) {
    center_of_gravity=a;
}

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

class Circle:public Shape {
private:
    float radius;
public:
    float x;
    float y;
    Circle();
    Circle(float);
    virtual float circumference(void);
    virtual float area(void);
};

Circle::Circle(void) {
}

Circle::Circle(float a) {
    radius=a;
}

float Circle::area(void) {
    float area_of_circle;
    const float pi=3.14159;
    area_of_circle=radius*radius*pi;
    return area_of_circle;
}

float Circle::circumference(void) {
    float circumference_of_circle;
    const float pi=3.14159;
    circumference_of_circle=2*radius*pi;
    return circumference_of_circle;
}

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

class Square:public Shape {
private:
    float length;
public:
    Square();
    Square(float);
    virtual float circumference(void);
    virtual float area(void);
};

Square::Square(void) {
}

Square::Square(float a) {
    length=a;
}

float Square::area(void) {
    float area_of_circle;
    area_of_circle=length*length;
    return area_of_circle;
}

float Square::circumference(void) {
    float circumference_of_square;
    circumference_of_square=4*length;
    return circumference_of_square;
}

int main() {
    float a,b;
    cout<<"Enter coordinates of center of gravity: "<<endl;
    cin>>a>>b;
    Point center_of_grav(a,b);
    cout<<"Enter length of square: "<<endl;
    cin>>a;
    Square square(a);
    cout<<"Enter radius of circle: "<<endl;
    cin>>a;
    Circle circle(a);
    Shape *shape1=&circle;
    Shape *shape2=&square;
    cout<<"Area of circle is "<<shape1->area()<<", circumference is "<<shape1->circumference()<<endl;
    cout<<"Area of square is "<<shape2->area()<<", circumference is "<<shape2->circumference()<<endl;
}

可以吗?如何实现重心移动功能? 如何读取 Circle 和 Square 的重心(它继承自 class Shape)?当他们说“......以及阅读数据成员”时,他们是认真的(我认为)。

编辑:

在我将所有建议放在一个地方后:

    #include <iostream>
    using namespace std;

    class Point{
    private:
    float x;
    float y;
    public:
    Point();
    Point(float,float);
    ~Point();
    friend class Shape;
    };

    Point::Point(){
    }

    Point::Point(float a,float b){
    x=a;
    y=b;
    }

    Point::~Point(){
    }

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

    class Shape{
    public:
    Shape(void);
    Shape(Point);
    virtual float area(void)=0;
    virtual float circumference(void)=0;
    protected:
    float x_coordinate;
    float y_coordinate;
    Point center_of_gravity;
    };

    Shape::Shape(void){
    }

    Shape::Shape(Point a){
    center_of_gravity=a;
    x_coordinate=a.x;
    y_coordinate=a.y;
    }

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

    class Circle:public Shape{
    private:
    float radius;
    public:
    Circle();
    Circle(Point,float);
    virtual float area(void);
    virtual float circumference(void);
    };

    Circle::Circle(void){
    radius=0;
    }

    Circle::Circle(Point p,float a) : Shape(p), radius(a){
    }

    float Circle::area(void){
    float area_of_circle;
    const float pi=3.14159;
    area_of_circle=radius*radius*pi;
    return area_of_circle;
    }

    float Circle::circumference(void){
    float circumference_of_circle;
    const float pi=3.14159;
    circumference_of_circle=2*radius*pi;
    return circumference_of_circle;
    }

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

    class Square:public Shape{
    private:
    float length;
    public:
    Square();
    Square(Point,float);
    virtual float area(void);
    virtual float circumference(void);
    };

    Square::Square(void){
    length=0;
    }

    Square::Square(Point p,float a) : Shape(p), length(a){
    }


    float Square::area(void){
    float area_of_circle;
    area_of_circle=length*length;
    return area_of_circle;
    }

    float Square::circumference(void){
    float circumference_of_square;
    circumference_of_square=4*length;
    return circumference_of_square;
    }

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

    int main(){
    float a,b;
    cout<<"Enter coordinates of center of gravity: "<<endl;
    cin>>a>>b;
    Point center_of_grav(a,b);
    cout<<"Enter length of square: "<<endl;
    cin>>a;
    Square square(center_of_grav,a);
    cout<<"Enter radius of circle: "<<endl;
    cin>>a;
    Circle circle(center_of_grav,a);
    Shape *shape1=&circle;
    Shape *shape2=&square;
    cout<<"Area of circle is "<<shape1->area()<<", circumference is "<<shape1->circumference()<<endl;
    cout<<"Area of square is "<<shape2->area()<<", circumference is "<<shape2->circumference()<<endl;
    }

回答你的问题,不行。您的代码确实显示了一些非常清晰的思路,所以这很好。它只需要完成。所有 classes 的所有数据成员都必须在构造对象时赋值。否则,他们会得到随机值,这绝不是好的做法。所以在 Shape 构造函数中初始化 CG。

此外,如果您想让它们代表 CG,请从圆圈中删除 x 和 y -- 该信息已被继承。

最后,实现一个移动CG的功能,我建议在Shape class中添加一个setter方法,它可以被其他两个继承class es。有了这些,你应该可以开始了。

1.Constructor设计

你将如何设置他们的重心?

Point center_of_grav(a,b);
...
Square square(c);   // what's the gravity center ?  

您必须设计派生的构造函数,使其具有构造基类所需的所有信息:

Square square(center_of_grav, c); 

为此,您必须按以下方式定义它(当然相应地调整 class 定义):

Square::Square(Point p, float a) : Shape(p), lentgh(a) {
    // ... reserve this for more complex initisalisations
}

请注意,您的默认构造函数未初始化对象。

2.Design 形状

非常重要: Shape 是具有虚函数的多态class。在这种情况下,您应该养成定义虚拟析构函数的习惯。

小提示:直接创建 Shape 对象是没有意义的。这是一个抽象的概念。没有默认规则来计算可应用于大多数形状的面积或周长。因此,我强烈建议将这两个函数定义为纯虚函数:

class Shape {
    ...
    virtual float circumference(void) =0;  // pure virtual
    virtual float area(void) = 0; 
    ...
};

优点:一旦你在 class 中有一个纯虚函数,这个 class 就变得抽象了,你将无法实例化那个 [=70= 的对象] 错误。编译器将确保您只实例化抽象概念的具体派生。

3.Make确保您的代码符合要求

好吧,这是一个细节,您当然已经处理好了,但是:

Classes should have specific functions for calculating circumference and area, as well as for reading data members.

所以我认为您应该预见一些 getter 访问受保护的数据:

示例:

class Shape {
    ...
    Point get_gravity_center();  
    ...
};

Point Shape::get_gravity_center() {
    return center_of_gravity;
}

其他的我让你完成。简单地想象一下,您必须在 main() 中打印圆的描述(圆心和半径的坐标),然后您会看到缺少的 getter。

编辑您的问题:

由于我们已经在形状级别为重心定义了 getter,因此您不需要在派生中再次定义它。然后您可以简单地在 main() 中调用它。问题是您还需要访问该点的坐标。所以:

class Point {
    ... 
    float get_x() { return x; }
    float get_y() { return y; }
    ...
};

有了这个你可以在main()中写:

cout << "Circle of center ("<<circle.get_gravity_center().get_x()<<","
                            << circle.get_gravity_center().get_y()<<")"<<endl;

P.S:使用 center_of_gravity 作为形状的成员,您不再需要复制该点的坐标。