【问题标题】:C++ inheritance and virtual funcionsC++ 继承和虚函数
【发布时间】:2015-08-23 06:40:25
【问题描述】:

这是我的任务:

设计类 Circle 和 Square 继承自 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 的重心(它继承自 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;
    }

【问题讨论】:

  • 我会将circumference()area() 声明为Shape 类中的纯方法。 (virtual float area() = 0;)。
  • 正方形没有圆周
  • CircleSquare的成员函数中直接访问protected(子类可见)成员变量center_of_gravity
  • 首先,学习如何从子类调用父构造函数(以及在一般的构造函数初始化列表的过程中),然后修改你的SquareCircle 构造函数将点作为额外参数。
  • 关于@EdHeal 评论的旁注:“周长”是这个词

标签: c++ function class inheritance virtual


【解决方案1】:

1.构造函数设计

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

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

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

Square square(center_of_grav, c); 

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

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

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

2.造型设计

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

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

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

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

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

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

类应该具有计算周长的特定函数 和区域,以及用于读取数据成员

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

例子:

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

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

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

根据您的问题进行编辑:

由于我们已经在形状级别为重心定义了吸气剂,因此您无需在派生中再次定义它。然后你可以简单地在 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 作为 shape 的成员,您不再需要复制该点的坐标。

【讨论】:

  • 您好 Christophe,感谢您的回复。请看我的第一篇文章,我在那里放了新代码。但是,我仍然不确定返回 center_of_gravity 变量的函数。我应该在新代码中修改什么,例如,打印我在主程序中声明的圆形和正方形的 center_of_gravity(用户还将在那里输入 x 和 y 坐标,如您所见)?
  • @etf 您好,我已编辑,试图回答您的其他问题。
  • 非常感谢!再问一个问题:Square的构造函数需要一行实现吗? Square::Square(Point p, float a) : Shape(p), lentgh(a) { // ... 为更复杂的初始化保留这个 }
  • 对于基本构造函数,您必须这样做。对于 memer,您可以选择“在线”构造它们,或者让它们默认构造并在构造函数的主体中初始化它们
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 2015-08-07
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多