Question

I am trying to pass an array of Student

into the function processStudent(string myFilename, Student* myArray, int &mySize). But it is giving me different kind of errors.

The Student() does nothing, but I tried to assign them some sort of value, it still give the exact same error message:

In the main I have this:

// Create an array of students, with the size of theMax (256)
Student* arrayOfStudent= new Student[theMax];

// An integer that will keep track of actually how many students
// Because when we loop, we want to loop within the cell
// that actually have data or student.
int actualSize = 0;

// Invoke the helper function to set up the array of students
// It passed the arryOfStudent by reference, so the changes
// inside of the function will be reflected when it returns
processStudent(filename, arrayOfStudent, actualSize);

The function is like this:

void processStudent(string myFilename, Student* myArray, int& mySize)
{
    // Something here, but removed still gives that error
}

// In the class Student's cpp file

Student::Student() 
{
    // Nothing here
}

Error Message:

new-host-2:csci135p1 george$ g++ -Wall -o csci135p2main csci135p2main.cpp
Undefined symbols for architecture x86_64:
  "Student::Student()", referenced from:
      _main in cc3fTXti.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

I have been stripping and stripping down my code, but this error just won't go away. I want to create this array, and pass it to the processStudent function, so it can set up each one when reading the file.

Was it helpful?

Solution

You should ask yourself some questions that could help you:

"How do I create new instance of Student?"
Well, I do it like this: Student* s = new Student(); - it creates new object and stores the referrence to it as a pointer (Student*)

"So how do I create an array of 10 Students?"
Well, it's probably going to be an array of pointers to new Students and I will probably have to call new more than once... by thinking this way you would easily end up with something like this:

Student** students = new Student*[10];
for (int i = 0; i < 10; ++i)
    students[i] = new Student();

... which means, that when you clean it up, you will have to call delete on every Student* plus you'll have to clean up the array itself: call delete[] on Student** - and when you realize the ugly memory management connect with array of pointers, it should make you look for simpler and better ways of implementing it, thus you should end up using std::vector instead of array, objects instead of pointers if it's possible and if it's not, then use smart pointers rather than naked pointers at least.

OTHER TIPS

The first error (which seems to have been removed from the question since I wrote this) is telling you that the second parameter of processStudent is a pointer-to-pointer, Student**, and not a pointer, Student*. That's odd since you show your declaration with a Student* parameter; are you sure that's the actual declaration from your code? Do you have a different declaration somewhere?

The second error is probably because you're not linking with the unit that contains the definition of the constructor. You're calling the compiler with just one source file (csci135p2main.cpp), and I'm guessing that you define the constructor in a different source file.

There error message is telling you the answer:

Student*’ to ‘Student**’

Change the type of the myArray argument in processStudent():

void processStudent(string myFilename, Student** myArray, int& mySize)
{
}

When an array is passed to a function it decays to a pointer:

void some_func(char* b) {...}

char buf[100];
some_func(buf);

When you pass the arrayOfStudent the array decays to a pointer, it just happens to be that the array is an array of pointers hence the **.


The linker is complaining that it cannot locate the definition of the default constructor for Student. The definition is contained in the Student.cpp file so compile all of the source files to resolve the linker error:

g++ -Wall -o csci135p2main csci135p2main.cpp Student.cpp

you'd better use a vector of Student (prefer using arrays only with basic types (int, char..) and vectors for everything else).

#include <vector>

std::vector<Student*> arrayOfStudent = new vector<Student*>();
/* ... */
processStudent(filename, arrayOfStudent, actualSize);

and

void processStudent(std::string& filename, vector<Student*>& arrayOfStudent, int& actualSize) {
/* ... */
}

I'm not sure whether that would solve your problem, but at least that's a better use...

Your code is bug-prone hard-to-maintain exception-unsafe C++. In modern C++, you should use std::vector<Student>, with Student class implementing move semantics, or vector<shared_ptr<Student>> or vector<unique_ptr<Student>> based on the ownership (shared or not) of your Student instances.

And your function prototype should be like this if student array is an input/output parameter:

void processStudent(const std::string & filename, std::vector<Student> & students);

Instead, if the processStudent function creates the array of students (e.g. based on the content of file), just return it as a return value (this is very efficient thanks to move semantics):

std::vector<Student> processStudent(const std::string & filename);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top