QuarterOnion
QuarterOnion

Reputation: 21

Why is my derived class showing as abstract?

Getting an error that says

..\src\CS20 Lab 2 Part 2.cpp:75:38: error: invalid new-expression of abstract class type 'CS_Student'

Base Class:

    /*
 * Student.h
 *
 *  Created on: Jan 23, 2020
 *      Author: Student
 */

    enter code here

#ifndef STUDENT_H_`#define STUDENT_H_
#include <string>
using namespace std;

class Student {
protected:
    string *name;
    int *age;
public:
    Student();

    void setName(string s) ;
    void setAge(int i);
    string getName() const;
    int getAge() const;
    virtual void print() = 0;

    virtual ~Student();

};
#endif /* STUDENT_H_ */

Student.cpp:

/*
 * Student.h
 *
 *  Created on: Jan 23, 2020
 *      Author: Student
 */

#ifndef STUDENT_H_
#define STUDENT_H_
#include <string>
using namespace std;

class Student {
protected:
    string *name;
    int *age;
public:
    Student();

    void setName(string s) ;
    void setAge(int i);
    string getName() const;
    int getAge() const;
    virtual void print() = 0;

    virtual ~Student();

};

#endif /* STUDENT_H_ */

Derived Class:

/*
 * CSStudent.cpp
 *
 *  Created on: Jan 23, 2020
 *      Author: Student
 */

#include <string>
#include <iostream>

#include "CS_Student.h"
#include "Student.h"
using namespace std;

CS_Student::CS_Student() {
    favProgLang = new string;
    cout << "CS_Student object created!" << endl;

}
void CS_Student::setFavProgLang(string s){
    *favProgLang = s;
}
string CS_Student::getFavProgLang() const{
    return *favProgLang;
}
void CS_Student::print() const{
    cout << "\nPRINT REPORT FOR CS_STUDENT OBJECT" << endl;
    cout << "\tName: " << *name << endl;
    cout << "\tAge: " << *age << endl;
    cout << "\tFavorite Programming Language: " << *favProgLang << endl;
}
CS_Student::~CS_Student() {
    delete favProgLang;
    cout << "CS_Student object destroyed!" << endl;
}

/*
    void setFavProgLang(string s);
    string getFavProgLang() const;
    void print() const;
 */

Derived header:

/*
 * CSStudent.h
 *
 *  Created on: Jan 23, 2020
 *      Author: Student
 */

#ifndef CS_STUDENT_H_
#define CS_STUDENT_H_

#include <string>
#include "Student.h"

#include <iostream>
using namespace std;


class CS_Student: public Student {
private:
    string *favProgLang;
public:
    CS_Student();

    void setFavProgLang(string s);
    string getFavProgLang() const;
    void print() const;

    virtual ~CS_Student();
};

#endif /* CS_STUDENT_H_ */

Main:

#include "CS_Student.h"
#include "EnglishStudent.h"

/*******************************************************************************
* Function Prototypes
*******************************************************************************/
#include <iostream>
#include <string>

using namespace std;

void getInput(CS_Student**, const int);
void getInput(EnglishStudent**, const int);
void display(Student*);

/*******************************************************************************
* int main()
*   Starting point of the program.
*
* Output:
*   An integer to signal to the OS the exit code.
*******************************************************************************/

int main() {
    // variables
    const int CS_SIZE = 2;
    const int ENG_SIZE = 3;
    CS_Student* csArray[CS_SIZE];
    EnglishStudent* engArray[ENG_SIZE];

    // call the getInput method overloads for both arrays
    getInput(csArray, CS_SIZE);
    getInput(engArray, ENG_SIZE);

    // call the polymorphic display function for both arrays
    for (int i = 0; i < CS_SIZE; i++) {
        display(csArray[i]);
    }
    for (int i = 0; i < ENG_SIZE; i++) {
        display(engArray[i]);
    }

    // release the dynamic memory for objects inside both arrays
    for (int i = 0; i < CS_SIZE; i++) {
        delete csArray[i];
    }
    for (int i = 0; i < ENG_SIZE; i++) {
        delete engArray[i];
    }

    // terminate
    return 0;
}

/*******************************************************************************
* void getInput(CS_Student** objArray, const int SIZE)
*   Use a for loop to create dynamic CS student objects. Prompt the user for the
*   name/age/favorite programming language of each CS student. Store the
*   information in the dynamic object.
*
* Inputs:
*   objArray - a double-pointer that should be treated as an array of dynamic
*              CS student objects
*   SIZE     - a constant integer that represents the size of the array
*******************************************************************************/

void getInput(CS_Student** objArray, const int SIZE) {
    // variables
    string name = "", fpl = "";
    int age = 0;

    // for each CS student
    for (int i = 0; i < SIZE; i++) {
        // create the dynamic CS student object
        objArray[i] = new CS_Student();

        // prompt and store the name of the current CS student
        cout << "Enter the name for CS student #" << i + 1 << ": ";
        getline(cin, name);

        // prompt and store for the age of the current CS student
        cout << "Enter the age for CS student #" << i + 1 << ": ";
        cin >> age;

        // need to ignore the newline in the buffer
        cin.ignore();

        // prompt and store the favorite programming language of the current
        // CS student
        cout << "Enter the favorite programming language for CS student #"
             << i + 1 << ": ";
        getline(cin, fpl);

        // add the data to the dynamic object
        objArray[i]->setName(name);
        objArray[i]->setAge(age);
        objArray[i]->setFavProgLang(fpl);
    }
}

/*******************************************************************************
* void getInput(EnglishStudent** objArray, const int SIZE)
*   Use a for loop to create dynamic English student objects. Prompt the user
*   for the name/age/favorite book of each English student. Store the
*   information in the dynamic object.
*
* Inputs:
*   objArray - a double-pointer that should be treated as an array of dynamic
*              English student objects
*   SIZE     - a constant integer that represents the size of the array
*******************************************************************************/

void getInput(EnglishStudent** objArray, const int SIZE) {
    // variables
    string name = "", book = "";
    int age = 0;

    // for each English student
    for (int i = 0; i < SIZE; i++) {
        // create the dynamic English student object
        objArray[i] = new EnglishStudent();

        // prompt and store the name of the current English student
        cout << "Enter the name for English student #" << i + 1 << ": ";
        getline(cin, name);

        // prompt and store for the age of the current English student
        cout << "Enter the age for English student #" << i + 1 << ": ";
        cin >> age;

        // need to ignore the newline in the buffer
        cin.ignore();

        // prompt and store the favorite book of the current English student
        cout << "Enter the favorite book for English student #"
             << i + 1 << ": ";
        getline(cin, book);

        // add the data to the dynamic object
        objArray[i]->setName(name);
        objArray[i]->setAge(age);
        objArray[i]->setFavBook(book);
    }
}

/*******************************************************************************
* void display(Student* obj)
*   A polymorphic function. Simply calls the (virtual) print method. Used to
*   demonstrate polymorphism. Any derived class that inherits from the Student
*   class can be used as an argument.
*
* Input:
*   obj - a pointer to an object that inherits from the Student class
*******************************************************************************/

void display(Student* obj) {
    obj->print();
}

Really confused because Student is my base class which has the pure virtual function virtual void print() = 0; and it's overridden in CS_Student void CS_Student::print() const I've also tried changing CS_Student here to Student and it doesn't change anything. Thanks in advance

Upvotes: 0

Views: 517

Answers (1)

user4581301
user4581301

Reputation: 33931

Base: virtual void print() = 0;

Derived: void print() const;

That extra const in the derived version changes the signature of the derived function, the instance variable this is const, so that it doesn't match the base function. Either the base must be const or the derived must not be const. Prefer the former.

Eg.

virtual void print() = 0;

becomes

virtual void print() const= 0;

In C++ and more recent standard revisions you can catch this more easily by marking all functions you expect to override a base class function with the override keyword. This almost always results in a more easily understood error message.

Eg.

void print() const override;

results in (on my tool chain)

error: 'void CS_Student::print() const' marked 'override', but does not override
     void print() const override;

Upvotes: 4

Related Questions