访问函数中的类数组
Access an array of class in a function
我制作了一个类为st[5]
的数组。并尝试用一个函数来显示st[5]
的数据。但是它不工作。
只显示第1类(st[0]
),并显示debug error Message。我不知道是什么问题。
下方为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
你在这里创建了一个指针数组:
Totscore *st[MAX];
但是你传递的是第一个元素:
PrintArray(*st);
把你的函数改成一个指向整个数组的指针就可以了:
void PrintArray(Totscore **stu){
for(int i=0; i< MAX; i++){
stu[i]->Display();
}
}
PrintArray(st);
导致未定义行为的几个主要问题:
-
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] = ' ';
}
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);
}
这段代码看起来很痛苦。以下几个技巧可以帮助您快速、轻松地改进代码:
在c++中,使用const
而不是#define
作为常量。
#define MAX 5 // Instead of this...
const int MAX = 5; // ...do this.
同样,用户std::string name
优于char *name
或char name[10]
。否则,你只是在用类写C,不幸的是,已经有足够多的类了。不要增加痛苦。:)
学习使用标准容器类型(vector、list、set和友元)而不是裸数组。没有理由不这样做,他们提供的内置功能是惊人的!当然,这是一个学习曲线。但你最终会表现得更好。
如果你想要一个对象数组,你必须声明数组为:
Totscore st[MAX];
并在堆栈上分配Totscore对象(删除"new")。最后,在不解引用的情况下调用print函数:
PrintArray(st);
首先,我会告诉你你需要做什么(不要求你改变整个代码)才能使你的代码工作,然后解释为什么你的代码不能工作:
将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!
完成了!
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 打印 2D 动态数组 c++ 函数
- C++数组函数
- 在数组函数指针中调用void
- 数组函数似乎没有找到最大值
- 使用数组函数和循环求解伪元编码|C
- 在头文件中的函数原型中获取指针数组:函数声明为 void
- 数组函数错误输出
- 读取文件,然后创建数组函数C++
- 指针数组函数参数-奇怪的行为
- 二维数组 - 函数
- "return"没有从数组函数返回正确的值
- 数组函数问题
- 数组函数的大小返回 int 的大小而不是数组
- 从数组函数中删除元素
- 如何从C++中最好地调用具有C99风格数组函数签名的函数
- 追加/打印/插入数组c++函数问题
- 如何将数组函数转换为指针函数
- 多维数组函数输出垃圾
- C++:数组函数的递归最大值