访问函数中的类数组

时间:2011-12-10 14:06:35

标签: c++ arrays class

我创建了一个类st[5]的数组。并尝试使用函数显示st[5]的数据。但它不起作用。

仅显示第一个类(st[0]),并显示“调试错误消息”。我不知道问题是什么。

main功能位于底部。

#include <iostream>
using namespace std;

#define MAX 5       //size of array

//Class 'Student' 
class Student
{
public:
    int num;
    char name[10];
};

//Class 'Lscore' extends Student (virtual)
class Lscore : virtual public Student   
{
public: 
    int eng;    
};

//Class 'Nscore' extends Student (virtual)
class Nscore : virtual public Student
{
public:
    int math;   
};

//Class 'Totscore' extends Lscore, Nscore
class Totscore : public Lscore, public Nscore
{
public:
    Totscore();     //Constructor1
    Totscore(char name[], int num, int eng, int math); //Constructor2
    void Display();     //Print Myself
};

//Constructor1
Totscore::Totscore( )
{
}

//Constructor2
Totscore::Totscore(char name[10], int num, int eng, int math)
{       
    strcpy_s(this->name, 10, name);
    this->num = num;    
    this->eng = eng;
    this->math = math;  
}


//Print Myself
void Totscore::Display(){
    cout<<this->num<<"  "<<this->name<<"  ";
    cout<<this->eng<<"  "<<this->math<<"  "<<endl;
}


//Print Array (--- Problem Part !! ---)
void PrintArray(Totscore *stu){ 
    for(int i=0; i< MAX; i++){
        stu[i].Display();       
    }

}

//Main Function
int main(){
    Totscore *st[MAX];      //Class Array 'st'

    st[0] = new Totscore("A",101,85,77);
    st[1] = new Totscore("B",102,90,89);
    st[2] = new Totscore("C",103,80,55);
    st[3] = new Totscore("D",104,75,85);
    st[4] = new Totscore("E",105,85,85);

    PrintArray(*st);
}

然后运行屏幕。 (我无法上传图片,因为我的声誉很低。)

101  A  85  77

显示“调试错误消息”...

5 个答案:

答案 0 :(得分:4)

你在这里创建了一个指针数组:

Totscore *st[MAX];

但是你传递了第一个元素:

PrintArray(*st);

更改函数以获取指向整个数组的指针应该有效:

void PrintArray(Totscore **stu){ 
    for(int i=0; i< MAX; i++){
        stu[i]->Display();       
    }
}

PrintArray(st);

答案 1 :(得分:1)

首先,我将告诉您需要做什么(不要求您更改整个代码)以使代码工作,然后解释为什么您的代码不起作用:

将您的printArray实施为:

void PrintArray(Totscore **stu){ 
    for(int i=0; i< MAX; i++){
        stu[i]->Display();     
    }
}

然后将其称为:

PrintArray(st);

这应该有用。

现在为什么原始代码不起作用是因为你传递的是数组的第一个元素,它不能用于遍历声明为指针数组的数组。由于st被声明为指针数组,因此您需要传递数组的第一个元素的地址,而不是元素本身,以便您可以遍历指针数组。请注意,数组的元素类型为Totscore*,因此其地址为Totscore**


对于初学者来说这是非常复杂的,所以我建议一个更好,更强大和更容易的选择。使用std::vector作为:

std::vector<Totscore> st;

然后调用.push_back()向其插入元素:

st.push_back(Totscore("A",101,85,77));
st.push_back(Totscore("B",102,90,89));
st.push_back(Totscore("C",103,80,55));
//etc

PrintArray(st);

然后将PrintArray实现为:

void PrintArray(const std::vector<Totscore> & stu)
{ 
    for(size_t i=0; i< stu.size(); i++){
        stu[i].Display();     
    }
}

现在,您需要在代码中进行一项非常少的更改。使Display()函数成为 const 成员函数。

void Display() const;
               ^^^^^ //this makes the  function const!
                     //in its definition too, write const!

完成!

答案 2 :(得分:1)

导致未定义行为的几个主要问题:

  1. Student的默认构造函数未初始化其char数组。
  2. 通过值传递给构造函数的数组。
  3. 通过数组进行不正确的迭代。对象数组的内存布局与指向对象的指针数组不同。
  4. 嗯,还有一个内存泄漏,许多不必要的操作只是为了初始化数据。您应该使用构造函数初始化列表。在C / C ++中没有strcpy_s函数,它是一个可怕的微软发明。为什么不使用便携式strncpy

    以下是一些改进的代码:

    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    #define MAX 5       //size of array
    
    //Class 'Student' 
    class Student
    {
    public:
        Student (int num = 0) : num (num)
        {
            name[0] = '\0';
        }
    
        Student (const char *name, int num = 0) : num (num)
        {
            strncpy (this->name, name, sizeof (this->name));
        }
    
        int num;
        char name[10];
    };
    
    //Class 'Lscore' extends Student (virtual)
    class Lscore : virtual public Student   
    {
    public: 
        Lscore (int eng = 0) : eng (eng) {}
        int eng;    
    };
    
    //Class 'Nscore' extends Student (virtual)
    class Nscore : virtual public Student
    {
    public:
        Nscore (int math = 0) : math (math) {}
        int math;   
    };
    
    //Class 'Totscore' extends Lscore, Nscore
    class Totscore : public Lscore, public Nscore
    {
    public:
        Totscore() {}     //Constructor1
        Totscore(const char *name, int num, int eng, int math); //Constructor2
        void Display();     //Print Myself
    };
    
    //Constructor2
    Totscore::Totscore(const char *name, int num, int eng, int math)
            : Student (name, num), Lscore (eng), Nscore (math)
    {       
    }
    
    
    //Print Myself
    void Totscore::Display(){
        cout<<this->num<<"  "<<this->name<<"  "
            <<this->eng<<"  "<<this->math<<"  \n";
    }
    
    
    //Print Array (--- Problem Part !! ---)
    void PrintArray(Totscore **stu){ 
        for(int i=0; i< MAX; ++i){
            stu[i]->Display();       
        }
    
    }
    
    void DeleteArray(Totscore **stu){ 
        for(int i=0; i< MAX; ++i){
            delete stu[i];
        }
    }
    
    //Main Function
    int main(){
        Totscore *st[MAX];      //Class Array 'st'
    
        st[0] = new Totscore("A",101,85,77);
        st[1] = new Totscore("B",102,90,89);
        st[2] = new Totscore("C",103,80,55);
        st[3] = new Totscore("D",104,75,85);
        st[4] = new Totscore("E",105,85,85);
    
        PrintArray(st);
        DeleteArray (st);
    }
    

答案 3 :(得分:1)

如果需要对象数组,则必须将数组声明为:

Totscore st[MAX];

在堆栈上分配Totscore对象(删除“new”)。 最后,调用print函数而不解引用:

PrintArray(st);

您的原始代码将有效......

答案 4 :(得分:1)

这段代码看起来很痛苦。您可以使用一些提示来快速轻松地改进代码:

在C ++中,对于常量,优先于const而不是#define

#define MAX 5  // Instead of this...
const int MAX = 5;  // ...do this.

同样,用户std::string name超过char *namechar name[10]。否则,你只是在用C语言写C,不幸的是已经有足够的了。不要加重痛苦。 :)

学习使用标准容器类型(矢量,列表,集合和朋友)而不是裸阵列。没有理由不这样做,他们提供的内置功能是惊人的!当然,这里有一条学习曲线。但是你最终会表现得更好。