Firstly, using the >> method to read the student name assumes every student has a "one word" name, which is a bit unrealistic. If that is the condition of your problem, then consider
if( infile >> tempName )
{
infile >> idNumber; // loading data from file
for (int j = 0; j < 3; j++){
infile >> scores[j];
}
length = strlen(tempName);
name = new char[length + 1]; // for the null character
strcpy (name, tempName);
calculateAverageAndGrade();
}
When there is no name left in the file, there's no point in attempting to read further data.
But, you'll have to in some manner return an indicator of whether it was a successful read or not. I don't think using the Student constructor for the reading is a good idea.
Perhaps having the void StudentArrayV4::add () method do the actual reading, to temp variables. If successful, store the read values to the next available Student object.
This line
Student **temp = new Student*[numberOfStudents + physicalArraySize];
confuses me. If you know the number of students, why are you worried about finding end of file? Just loop that number of times when reading. What is physicalArraySize, where does that come from and why are you using it to set number of students in the temp array?