【问题标题】:What's wrong with this class C++ declaration?此类 C++ 声明有什么问题?
【发布时间】:2012-04-04 04:55:47
【问题描述】:

我的教授给了我们这门课,并告诉我们它不会编译。他说捐助者数组会与构造函数发生冲突。所以……为什么会这样?

我认为Donor 数组的名称可能会这样做,但这应该不是问题,因为成员数组donor 的名称区分大小写,因此与类名不同。

代码如下:

#ifndef DONORS_H
#define DONORS_H

#include <string>

#include "name.h"
#include "donor.h"

using namespace std;

const int 
    DONORS_LOAD_ERROR = 1,
    DONORS_UPDATE_ERROR = 2,
    DONORS_ADD_ERROR = 3;

const int MAX_DONORS = 100;

class Donors {
public:
    Donors() : size(0) {}
    void load(string filename);
    int getSize() {return size;}
    int find(Name name);
    int add(Name name);
    int add(Name name, Donation donation, int ytd);
    void processDonation(Name name, Donation donation);
    void update(string filename);
    void print();
private:
    Donor donorsList[MAX_DONORS];
    int size;
};

#endif

教授写道:

在这个版本中,我们采用了版本 2,添加了构造函数,并最大限度地利用了对象。

但是,构造函数的引入破坏了 Donors 类中数组数据成员的声明; 因此这个版本不能编译!!!!

我一直在和一个同学讨论这个问题,我们都很困惑。这个 C++ 类是怎么回事?

编辑:

编译器消息如下所示:

我突然想到 Donor 类有一个构造函数。既然我们还没有接触过十英尺长的向量,我们到底应该如何编译它?

编辑2:

这是捐助者类:

#ifndef DONOR_H
#define DONOR_H

#include "name.h"
#include "donation.h"

using namespace std;

class Donor {
public:
    Donor(Name n, Donation ld=Donation(0, 0), int y=0) : name(n), lastDonation(ld), ytd(y) {}
    Name getName() {return name;}
    Donation getLastDonation() {return lastDonation;}
    int getYtd() {return ytd;}
    void processDonation(Donation d);
private:
    Name name;  
    Donation lastDonation;
    int ytd;
};

#endif

【问题讨论】:

  • “不编译”是不够的错误描述,你知道的。
  • 您在尝试编译时收到了什么错误信息?
  • 编译错误是什么?
  • 由于您没有提供错误消息,因此我投票决定关闭它,因为这不是一个真正的问题。
  • 我们还需要看Donor类的声明

标签: c++ class


【解决方案1】:

没有Donor类的定义很难说,但我猜他在Donor类中添加了一个带参数的构造函数,所以它不会再有隐式默认构造函数了。

但是现在,没有默认构造函数,即可以不带参数调用的构造函数,你不能声明这种类型的数组,因为没有办法传递所需的参数!

【讨论】:

【解决方案2】:

我的猜测是 Donor 类(您没有包括在内)没有默认构造函数。如果是这样,你会得到一个编译器错误,因为这一行:

Donor donorsList[MAX_DONORS]; 

将尝试使用 Donor 没有的无参数构造函数。

如果您遇到讲师向您展示的错误,它将帮助您在课程中做得更好。然后,当您在现实生活中体验它们时,您会认出它们。如果你要学习 C++,“我和一个朋友看过这个,它应该可以正常编译”的策略永远无法替代尝试编译它并查看你得到什么错误。

【讨论】:

【解决方案3】:

你需要包含class Donor的定义。

从外观上看,我猜class Donor 有一个非默认构造函数,即。 e.接受一个或多个参数的构造函数。这种情况下class Donor的默认构造函数不是由编译器生成的,你必须自己定义。

创建donorsList需要默认构造函数,因为在创建对象数组时,每个对象都会调用默认构造函数。

【讨论】:

    【解决方案4】:

    考虑第一个Donors类:

    #ifndef DONORS_H
    #define DONORS_H
    
    #include <string>
    
    #include "name.h"
    #include "donor.h"
    

    到目前为止还可以。

    using namespace std;
    

    否! 切勿将using namespace std; 放在标头中的全局命名空间中。作者(你的教授)几乎保证了愚蠢的名称冲突,就像编译器在一些糟糕的用户代码中抱怨 distance

    const int 
        DONORS_LOAD_ERROR = 1,
        DONORS_UPDATE_ERROR = 2,
        DONORS_ADD_ERROR = 3;
    
    const int MAX_DONORS = 100;
    

    这些都是坏名字。保留为宏名称大喊大写。但请务必将它们用作宏名称。

    另外,最好将enum 用于此类常量。

    此外,更好地使用异常报告失败。

    class Donors {
    public:
        Donors() : size(0) {}
        void load(string filename);
    

    string 参数最好通过引用 const 来传递。

        int getSize() {return size;}
    

    这个方法应该是const

    此外,虽然前缀 get 在某些语言(如 Java 和 C#)中具有实际优势,它们支持自省(以及因此基于自省的工具),但在 C++ 中,它只是愚蠢的冗长——在大多数情况下,在这种情况下.

    最好将这个数学称为 name

    准则:考虑调用代码的可读性。

        int find(Name name);
    

    name 参数可能最好作为对 const 的引用传递。

        int add(Name name);
    

    name 参数可能最好作为对 const 的引用传递。

        int add(Name name, Donation donation, int ytd);
    

    namedonation 参数可能最好作为对 const 的引用传递。

    ytd 这个名字很糟糕。很难猜到是什么意思。

        void processDonation(Name name, Donation donation);
    

    namedonation 参数可能最好作为对 const 的引用传递。

    界面模棱两可:addprocess有什么区别?

        void update(string filename);
    

    name 参数可能最好作为对 const 的引用传递。

    这个方法的名字不好。

    几乎不可能猜到这个方法的作用。

        void print();
    

    这个方法应该在哪里打印一些东西,用什么格式?

    private:
        Donor donorsList[MAX_DONORS];
    

    此声明要求Donor 有一个可以不带参数调用的构造函数,即默认构造函数

        int size;
    };
    
    #endif
    

    考虑第二个Donor 类:

    #ifndef DONOR_H
    #define DONOR_H
    
    #include "name.h"
    #include "donation.h"
    

    到目前为止还可以。

    using namespace std;
    

    否! 切勿将using namespace std; 放在标头中的全局命名空间中。作者(你的教授)几乎保证了愚蠢的名称冲突,就像编译器在一些糟糕的用户代码中抱怨 distance

    class Donor {
    public:
        Donor(Name n, Donation ld=Donation(0, 0), int y=0) : name(n), lastDonation(ld), ytd(y) {}
    

    yytd 是坏名字。目前无法猜测它们是关于什么的。

    ld 是个坏名字。

    NameDonation 参数最好通过引用 const 来传递。

    注意:当有用户声明的构造函数时,比如上面那个,那么默认的构造函数不会自动生成

        Name getName() {return name;}
    

    这个方法应该是const

    此外,虽然前缀 get 在某些语言(如 Java 和 C#)中具有实际优势,它们支持自省(以及因此基于自省的工具),但在 C++ 中,它只是愚蠢的冗长——在大多数情况下,在这种情况下.

    最好把这个数学称为name

    准则:考虑调用代码的可读性。

        Donation getLastDonation() {return lastDonation;}
    

    参见上面的 cmets。

        int getYtd() {return ytd;}
    

    参见上面的 cmets。

        void processDonation(Donation d);
    

    参数最好通过引用const 来传递。

    private:
        Name name;  
        Donation lastDonation;
        int ytd;
    };
    
    #endif
    

    简而言之,Donors 类要求Donor 具有默认构造函数,但由于Donor 具有用户声明的构造函数,因此不会生成默认构造函数。

    一种解决方法是将简单数组替换为 std::vector 或其他集合,例如

    std::vector<Donor> donors_;
    

    std::map< std::string, Donor > donors_;
    

    【讨论】:

    • DonorsDonor 我认为的对象的容器。
    • 哦,名字的细微差别。我没看到。让我修复答案。好的,完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    相关资源
    最近更新 更多