Good day.

Task:

  1. Determine the class hierarchy (according to option).

  2. Define a static component in a class โ€” a pointer to the beginning of the linked list of objects and a static function for viewing the list.

  3. Implement classes.

  4. Write a demonstration program in which objects of different classes are created and placed in a list, after which the list is viewed.

main:

int main() { Worker worker1 = Worker(); worker1.setFio((char *) "WorkerFIO"); worker1.setAge(143); List test = List(); test.add(worker1); printArr(); worker1.~Worker(); } 

Staff class (basic, abstract)

 class Staff { public: Staff() {} virtual ~Staff() {} virtual void calcSalary() = 0; void setFio(char *fio) { ... } void setAge(int age) { ... } char* getFio() { ... } int getAge() { ... } protected: /*some fields*/ }; 

Worker class (inherited from Staff)

 class Worker : public Staff { public: Worker() {} ~Worker() {} void calcSalary() { ... } private: /* some fields */ }; 

List. Class objects inherited from Staff should be added to it. At the same time, there will be several classes derived from Staff; they should all be added to this list.

 struct staff { Staff st; staff *next; }; static staff *begin; static void printArr() { staff *curr = begin; while (curr != NULL) { std::cout<<curr->st.getFio()<<std::endl; curr = curr->next; } } class List { private: public: List() { begin = NULL; } List(Staff st) { begin = NULL; add(st); } ~List() {} void add(Staff st) { staff *s = new staff; s->st = st; if (begin == NULL) { begin = s; } else { staff *curr = begin; while (curr->next != NULL) { curr = curr->next; } curr->next = s; } } }; 

The essence of the problem:

 "C:\Program Files (x86)\JetBrains\CLion 2016.3.4\bin\cmake\bin\cmake.exe" --build G:\Development\C++\Lab4\cmake-build-debug --target Lab4 -- -j 4 [ 50%] Building CXX object CMakeFiles/Lab4.dir/main.cpp.obj In file included from G:\Development\C++\Lab4\main.cpp:14:0: G:\Development\C++\Lab4\List.h:12:11: error: cannot declare field 'staff::st' to be of abstract type 'Staff' Staff st; ^ In file included from G:\Development\C++\Lab4\main.cpp:13:0: G:\Development\C++\Lab4\Staff.h:4:7: note: because the following virtual functions are pure within 'Staff': class Staff { ^ G:\Development\C++\Lab4\Staff.h:9:18: note: virtual void Staff::calcSalary() virtual void calcSalary() = 0; ^ In file included from G:\Development\C++\Lab4\main.cpp:14:0: G:\Development\C++\Lab4\List.h:32:16: error: cannot declare parameter 'st' to be of abstract type 'Staff' List(Staff st) { ^ G:\Development\C++\Lab4\List.h:37:20: error: cannot declare parameter 'st' to be of abstract type 'Staff' void add(Staff st) { ^ G:\Development\C++\Lab4\List.h: In constructor 'List::List(Staff)': G:\Development\C++\Lab4\List.h:34:15: error: cannot allocate an object of abstract type 'Staff' add(st); ^ G:\Development\C++\Lab4\main.cpp: In function 'int main()': G:\Development\C++\Lab4\main.cpp:23:21: error: cannot allocate an object of abstract type 'Staff' test.add(worker1); ^ 

What is the problem, I realized. It is impossible to just take and create an object of an abstract class (he is an abstract one). The next question is how to add class objects derived from an abstract class to the list. There will be several derived classes.

2 answers 2

The compiler curses because you put the base class body into the staff structure:

 struct staff { Staff st; // <=== staff *next; }; 

Accordingly, when creating an instance of the staff structure, an instance of the Staff class will also be created, and its fields will be stored inside this structure. Because of this, we cannot store derived classes in st (there is not enough reserved space).

To solve your problem you need to use pointers :

  • or not knowing with explicit new and delete :

     struct staff { Staff *st; staff *next; }; 
  • or owning (if you are using C ++ 11):

     struct staff { std::unique_ptr<Staff> st; staff *next; }; 

The pointer has absolutely no difference how much space the class data takes, so it can address any descendant implementing the virtual methods of the base class.

PS In general, the compiler curses the impossibility of generating an instance of the Staff class due to the presence of purely virtual methods in it. At the same time, the descendant classes of the compiler are not interesting, since the field can contain only instances of the Staff .

PPS As correctly noted by @Harry , in C and C ++, unlike Java, variables are stored by value (that is, by the place of declaration), unless otherwise specified. In other words, any variable is not a link, but a value itself with a previously allocated space of constant size.

    Paraphrasing O. Bender - Heavy Java legacy? :)

    Do not pass in C ++ such things by value:

     void add(Staff st); 

    It is necessary to work with pointers (or links, which, in general, the same thing) ...

     struct staff { Staff st; staff *next; }; 

    The same problem - in fact, an abstract class instance should be created here. How?

    So add, for example, pointers.

    PS You yourself are not confused in Staff and staff ?

    Pps by the way

     Worker worker1 = Worker(); 

    You can write easier:

     Worker worker1; 
    • Yes, you guessed it, Java is to blame for everything =) - Alexander Kandrin
    • According to this: Worker worker1 = Worker(); - a very characteristic thing ... - Harry