我创建了一个类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
显示“调试错误消息”...
答案 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)
导致未定义行为的几个主要问题:
Student
的默认构造函数未初始化其char数组。嗯,还有一个内存泄漏,许多不必要的操作只是为了初始化数据。您应该使用构造函数初始化列表。在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 *name
或char name[10]
。否则,你只是在用C语言写C,不幸的是已经有足够的了。不要加重痛苦。 :)
学习使用标准容器类型(矢量,列表,集合和朋友)而不是裸阵列。没有理由不这样做,他们提供的内置功能是惊人的!当然,这里有一条学习曲线。但是你最终会表现得更好。