1

So i'm trying to create a private member array on my School class where i'm going to be holding the address of some student objects. My goal is to simulate the stusents entering the school building if the capacity of the building allows as such (think of the problem with small numbers) I have managed to implement the "address object part" but i have an issue concerning the size of the array. The variable which gives the size of the array is also a private member of the same class. That being said the compiler gives the error:

error: invalid use of non-static data member ‘School::class_capacity’

148 | Student* pointer_array[class_capacity];

Here's School class:

class School
{
    private:
      int class_capacity;
      Student* pointer_array[class_capacity];
   public:
        School(const int capacity)//constructor
      :class_capacity(capacity)
      {
        cout << "A New School has been created!" << endl;
      };
      ~School(){//destructor
        cout << "A School to be destroyed!" << endl;
      }; 
      void enter(Student* student, int stc=0/*student counter*/);
}

Student class is :

class Student 
{
private:
    string name;
    int no_floor;
    int no_classroom;
public:
    Student(const string& nam,int no_fl,int no_cla)//constructor
    : name(nam), no_floor(no_fl), no_classroom(no_cla)
    {
      cout << "A new student has been created! with name " << name << " heading to floor: "<< no_floor << " class: " << no_classroom << endl;
    };

    ~Student()//destructor
    {
      cout << "A Student to be destroyed! with name " << name << " is at "<< " class: " << no_classroom;

    };

Lastly my main where i allocate an array of pointers to Student objects.

int main(void)
{
//Student creation
       int i,floor,classroom;
       string stname;
       Student* students[5];
       for(i=0; i<5; i++)
       {
          cin >> stname;
          cin >> floor;
          cin >> classroom;
          students[i] = new Student(stname, floor, classroom);
       }
       for(i=0; i<5; i++)
       {
         delete students[i];
       }
}

And the enter function code:

void School::enter(Student* student, int stc/*student counter*/)
{
  pointer_array[stc] = student;
  (pointer_array[stc])->print();
  cout << " enters school!" << endl;
}

The array i'm trying to create in School class is meant to keep a pointer to already created Student objects on my main.
Does anybody know how to solve this? Again library usage is forbidden

  • 2
    You probably don't want an array of pointers. I recommend going over your notes again. Come back when you've actually attempted something and run into a wall. – sweenish Nov 12 '20 at 16:25
  • @sweenish hey there thanks for the answer! Unfortunately i do need one. :\ They just told me that it's either this or creating a list from scratch (without including std::list) – ScatterBrainer Nov 12 '20 at 16:27
  • You cant define Variable Length Array (VLA) in C++ so also more precisely inside a class. VLA works inside functions for most compiler since this is `C` extension and compilers by default allow to mix C++ a C code. In C++ for runtime sized array use `std::vector`. – Marek R Nov 12 '20 at 16:28
  • 1
    You want a `Student* pointer_to_array;` as the class member and then in the constructor you'll do `pointer_to_array = new Student[size_of_array_needed]`. Then you'll also need to follow this: https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – NathanOliver Nov 12 '20 at 16:30
  • I see literally no reason for an array of pointers, unless Student is a base class. I also don't like that `School` is both a school, and a class that manages a dynamic array. That should be split into two classes. – sweenish Nov 12 '20 at 16:30
  • The instructor is outdated, teaching bad-practice. I would use `std::vector` as the primary standard solution, but you cannot use it now. You need to learn everything now - from memory management to RAII. I am sure that is not what your instructor demands. But that would be the right thing to do... – Red.Wave Nov 12 '20 at 16:33
  • @NathanOliver thank you so much for the answer!! i will try it and come back for the results – ScatterBrainer Nov 12 '20 at 16:33
  • @sweenish the actual program is.. a lot bigger. Trust me that's all the code you'll need for this problem. Just assume i have another class Student that is correctly implemented – ScatterBrainer Nov 12 '20 at 16:35
  • @sweenish due to popular demand i added the Student class as well if you want to check it out! – ScatterBrainer Nov 12 '20 at 16:42
  • And I still see zero reason for an array of pointers to Students. It should probably just be a dynamic array of Students. I also disagree with Red.Wave to an extent. This kind of knowledge is good for students to have, especially if we are in something like a Data Structures class where writing the dynamic array *is* the point of the assignment. – sweenish Nov 12 '20 at 16:48
  • Why don't these courses just have you create a generic vector class, instead of disguising it as a `School` that's chock-full of pointers that are unnecessary? I see assignments like *You are to design an entire shopping mall and parking lot. No vectors allows* -- Seriously, does that make *any* sense? – PaulMcKenzie Nov 12 '20 at 16:52
  • For what it's worth, that's exactly what I did in my class. All of my Data Structure assignments were to just mimic a chunk of the X data structure from the Standard Library, and grading was simply running the class through a test suite. In OOP, I still had little "themes" like what is seen here, but the grading was still to run the classes through a test suite. I think some profs do it this way because they feel it makes the assignment more "interesting." My take was that mimicking Standard Library behavior was interesting enough at the 400-level. – sweenish Nov 12 '20 at 16:56
  • @sweenish Will have to agree. Anybody could use library and it would be easy then. So...What do you think would be the best thing to do in my case? – ScatterBrainer Nov 12 '20 at 16:58
  • @ScatterBrainer See my first comment. The answers below will get you started, but you've shown no code to troubleshoot, just incomplete boilerplate. Per [ask] and [mre], this is still not what I'd consider a "good" question for this site. – sweenish Nov 12 '20 at 17:00
  • @sweenish ok let me fix my question real quick – ScatterBrainer Nov 12 '20 at 17:04
  • just posted the update – ScatterBrainer Nov 12 '20 at 17:07
  • @ScatterBrainer `Student* pointer_array[class_capacity];` -- This is not legal C++, that's the bottom line. Given that you have not accepted any of the answers so far, it is not clear what you are asking for. A dynamic array of type `T` is done (in your case) by declaring a `T*` and at some point `T* x = new T[number_of_elements];` and later `delete [] x;` -- Other than that, what issue do you see with this? – PaulMcKenzie Nov 12 '20 at 17:43
  • @PaulMcKenzie I mean, OP's comments on answers below and the newer code posted are demonstrating a lack of knowledge at a foundational level. They're not outright saying it's for a class (I hope it's a class and not an interview), but my guess is that someone who has the link handy posts the good book link and close this as vague. – sweenish Nov 12 '20 at 19:26
  • @PaulMcKenzie trust me this question wouldn't be here if i was allowed to create a default constructor...If i incorprate this answer i'd have to go with something like T* x = new T("a name", a floor number, a class number). I don't want that. I don't want to create new objects, all i'm trying to do is create an array of pointers to the already existing objects. Do you have any ideas on how i could do it or even if what i'm writing above is completely off track? Thanks for the asnwer btw – ScatterBrainer Nov 12 '20 at 19:44

3 Answers3

1

Without using std::vector you'd need to do your own dynamic array management

class School
{
private:
    int class_capacity;
    Student* students;
public:
    School(const int capacity)//constructor
      :class_capacity(capacity)
    {
        students = new Student[capacity];
        cout << "A New School has been created!" << endl;
    };

    ~School(){//destructor
        delete[] students;
        cout << "A School to be destroyed!" << endl;
    }; 

    // Disable copying to avoid accidental double-deletion of array
    School(School const&) = delete;
    School& operator=(School const&) = delete;
};
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • thank you so much for the answer! Truth be told since my actual code is huge i neglected to mention that Student class constructor has an initializer list. So please check the post again for the updated version. Again thanks for the time :) – ScatterBrainer Nov 12 '20 at 16:41
  • Would the students need to be individually destroyed? If it's an array of pointers to students, my assumption is that those pointers were also dynamically allocated. I am not aware that deleting the dynamic array is sufficient. – sweenish Nov 12 '20 at 16:50
  • @sweenish do you want me to post the main() too to see the full action? SInce the school is going to have many students i allocated an array of pointers to objects there. – ScatterBrainer Nov 12 '20 at 17:00
  • This is why i was avoiding new/delete with the Student* pointer_array .. Because i want this array to be a pointer to the array of pointers to objects (the students) (i don't know if that makes sense) – ScatterBrainer Nov 12 '20 at 17:03
0
Student* pointer_array[class_capacity];

is not legal code since class_capacity is not known at compile time. You'll have to use a dynamically allocated array.

Use of std::vector<Student> will be appropriate most of the time. Since you are not allowed to use std::vector, your only option is to use

Student* student_array; // Not pointer_array.

as the member variable. Memory for the array can be allocated in the constructor.

   School(const int capacity) : class_capacity(capacity),
                                student_array(new Student[capacity]) {}

Please note that you need to follow The Rule of Three when you manage dynamic memory in your class.


Update, in response to OP's comment.

I would suggest adding a default constructor to Student.

// Default constructor, implemented using the other constructor.
Student() : Student("", 0, 0) {}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

I finally managed to find the answer.The classes should look something like this.

School class:

class School
{
    private:
      int class_capacity;
      Student** pointer_array;
   public:
        School(const int capacity)//constructor
      :class_capacity(capacity)
      {
        pointer_array = new Student*[capacity];
        cout << "A New School has been created!" << endl;
      };
      ~School(){//destructor
        delete [] pointer_array;
        cout << "A School to be destroyed!" << endl;
      }; 
      void enter(Student* student, int stc=0/*student counter*/);
}

Class student , main and enter function stays as is.