【问题标题】:Derived classes' attributes are empty派生类的属性为空
【发布时间】:2021-12-20 00:29:29
【问题描述】:

我是 C++ 新手,目前正在玩继承。我正在创建一个分别由 Rectangle 和 Triangle 类继承的基础 Polygon 类。从那里我想打印出calcArea 中定义的区域。但是,我的派生类实例的输出似乎为空。

据我了解,Polygon:(name, width, height) 可以帮助初始化基类中已经存在的变量。感谢大家的帮助!

这是我的代码:

#include <iostream>
#include <string>

using namespace std;

enum Polytype {POLY_PLAIN, POLY_RECT, POLY_TRIANG};

class Polygon
{
    public:
        Polygon(string name, double width, double height){
            _name = name;
            _width = width;
            _height = height;
            _polytype = POLY_PLAIN;
        }

        virtual ~Polygon()
        {
            cout << "Destroying polygon" << endl;
        }

        virtual Polytype getPolytype(){
            return _polytype;
        }

        virtual void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        virtual string getName(){
            return _name;
        }

        virtual double calcArea(){
            return _width * _height;
        }

    private:
        string _name;
        double _width;
        double _height;
        Polytype _polytype;

};

class Rectangle: public Polygon
{

    public:
        Rectangle(string name, double width, double height) : Polygon(name, width, height){
            _polytype = POLY_RECT;
        };

        ~Rectangle()
        {
            cout << "Destroying rectangle" << endl;
        }

        Polytype getPolytype(){
            return _polytype;
        }

        void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        double calcArea(){
            return _width * _height;
        }

        string getName(){
            return _name;
        }

    private:
        string _name;
        double _width;
        double _height;
        Polytype _polytype = POLY_RECT;
};

class Triangle: public Polygon
{
    public:
        Triangle(string name, double width, double height) : Polygon(name, width, height){
            _polytype = POLY_TRIANG;
        };

        ~Triangle()
        {
            cout << "Destroying triangle" << endl;
        }

        Polytype getPolytype(){
            return _polytype;
        }

        void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        string getName(){
            return _name;
        }

        double calcArea(){
            return 0.5 * _width * _height;
        }

    private:
        string _name;
        double _width;
        double _height;
        Polytype _polytype;

};


int main(){

    //Initialize rectangle and triangle and store them onto the stack
    Rectangle rect("RectA", 10.0, 20.0);
    Triangle triang("TriangB", 10.0, 20.0);

    cout << "Name is " << rect.getName() << endl;
    cout << "Name is "<< triang.getName() << endl;

    string rectArea = to_string(rect.calcArea());
    string triangArea = to_string(triang.calcArea());

    cout << "RectA's area is " << rectArea << endl;
    cout << "TriangB's area is " << triangArea << endl;

    return 0;
}

这是我的输出:

Name is 
Name is 
RectA's area is 0.000000
TriangB's area is 0.000000
Destroying triangle
Destroying polygon
Destroying rectangle
Destroying polygon

【问题讨论】:

  • 派生类中的成员变量与基类中的成员变量是分开的,您应该删除它们。您只需要覆盖与基础具有不同行为的方法,这样您就可以删除其中的大部分

标签: c++ inheritance


【解决方案1】:

我意识到我不必在我的子类中重新声明私有变量。这可能是它返回 null 的原因。

#include <iostream>
#include <string>

using namespace std;

enum Polytype {POLY_PLAIN, POLY_RECT, POLY_TRIANG};

class Polygon
{
    public:
        Polygon(string name, double width, double height){
            _name = name;
            _width = width;
            _height = height;
            _polytype = POLY_PLAIN;
        }

        ~Polygon()
        {
            cout << "Destroying polygon" << endl;
        }

        virtual Polytype getPolytype(){
            return _polytype;
        }

        virtual void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        virtual string getName(){
            return _name;
        }

        virtual double calcArea(){
            return _width * _height;
        }

    protected:
        string _name;
        double _width;
        double _height;
        Polytype _polytype;

};

class Rectangle: public Polygon
{
    public:
        Rectangle(string name, double width, double height) : Polygon(name, width, height){
            _polytype = POLY_RECT;
        };

        ~Rectangle()
        {
            cout << "Destroying rectangle" << endl;
        }

        Polytype getPolytype(){
            return _polytype;
        }

        void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        double calcArea(){
            return _width * _height;
        }

        string getName(){
            return _name;
        }
};

class Triangle: public Polygon
{
    public:
        Triangle(string name, double width, double height) : Polygon(name, width, height){
            _polytype = POLY_TRIANG;
        };

        ~Triangle()
        {
            cout << "Destroying triangle" << endl;
        }

        Polytype getPolytype(){
            return _polytype;
        }

        void setPolytype(Polytype polytype){
            _polytype = polytype;
        }

        string getName(){
            return _name;
        }

        double calcArea(){
            return 0.5 * _width * _height;
        }
};


int main(){

    //Initialize rectangle and triangle and store them onto the stack
    Rectangle rect("RectA", 10.0, 20.0);
    Triangle triang("TriangB", 10.0, 20.0);

    cout << "Name is " << rect.getName() << endl;
    cout << "Name is "<< triang.getName() << endl;

    string rectArea = to_string(rect.calcArea());
    string triangArea = to_string(triang.calcArea());

    cout << "RectA's area is " << rectArea << endl;
    cout << "TriangB's area is " << triangArea << endl;

    return 0;
}

【讨论】:

    【解决方案2】:

    主要问题是子类中的变量掩盖了基类中的名称-因此您将值分配给基类中的变量,但稍后您会打印子类中默认初始化变量的值.

    您实际上主要需要删除代码。

    不过,我会重新考虑基类的名称。 Polygon 对于只有宽度和高度的类来说不是一个好名字。我将把它留给你。

    我已将所有endl 替换为\n。他们做同样的事情,但endl 刷新输出,这通常是不需要的 - 但它通常也很昂贵。

    例子:

    #include <iostream>
    #include <string>
    
    enum Polytype { POLY_PLAIN, POLY_RECT, POLY_TRIANG };
    
    class Polygon {
       public:
        Polygon(std::string name, double width, double height)
            : Polygon(name, width, height, POLY_PLAIN) {}
    
        virtual ~Polygon() { std::cout << "Destroying polygon\n"; }
    
        // make member functions that does not change the object `const`:
        virtual Polytype getPolytype() const { return _polytype; }
    
        virtual void setPolytype(Polytype polytype) { _polytype = polytype; }
    
        virtual const std::string& getName() const { return _name; }
    
        // in your case, the implementation could actually be in the base class - but
        // I've made it into a pure virtual here.
        virtual double calcArea() const = 0;      // no instances can be made of Polygon 
    
       protected:
        // only derived classes can access this constructor:
        Polygon(std::string name, double width, double height, Polytype ptype)
            : _name(name), _width(width), _height(height), _polytype(ptype) {}
    
        std::string _name;
        double _width;
        double _height;
        Polytype _polytype;
    };
    
    class Rectangle : public Polygon {
       public:
        Rectangle(std::string name, double width, double height)
            //use the protected base class ctor:
            : Polygon(name, width, height, POLY_RECT) {};
    
        ~Rectangle() { std::cout << "Destroying rectangle\n"; }
    
        // the only implementation needed in this sub class:
        double calcArea() const override { return _width * _height; }
    };
    
    class Triangle : public Polygon {
       public:
        Triangle(std::string name, double width, double height)
            : Polygon(name, width, height, POLY_TRIANG) {};
    
        ~Triangle() { std::cout << "Destroying triangle\n"; }
    
        // the only implementation needed in this sub class:
        double calcArea() const override { return 0.5 * _width * _height; }
    };
    
    int main() {
        // Initialize rectangle and triangle and store them onto the stack
        Rectangle rect("RectA", 10.0, 20.0);
        Triangle triang("TriangB", 10.0, 20.0);
    
        std::cout << "Name is " << rect.getName() << '\n';
        std::cout << "Name is " << triang.getName() << '\n';
    
        std::cout << "RectA's area is " << rect.calcArea() << '\n';
        std::cout << "TriangB's area is " << triang.calcArea() << '\n';
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多