Производный класс в C ++ - PullRequest
       1

Производный класс в C ++

1 голос
/ 11 октября 2011

У меня проблема с домашним заданием:

Desgin производный класс GraduateStudent от базового класса Student.Он добавляет элемент данных с именем Advisor для хранения имени студенческого советника по диссертации.Предоставить функции конструктора, деструктора, средства доступа и модификатора.Этот класс переопределяет функцию year, возвращая одну из двух строк («Магистр» или «PhD») в зависимости от количества часов, выполненных с использованием таблицы ниже.

Часы Год
<= 30 Мастеров</p>

(больше чем) 30 Кандидат наук

Я написал:

using namespace std;


class Student
{
public:
    Student( string s = "", int h = 0);
    ~Student();
    string getName() const;
    int getHours() const;
    void setName(string s);
    void setHours (int h);
    string year () const;
private:
    string name;
    int hours;

};

class GraduateStudent: private Student
{
public:
    GraduateStudent(string s = "", int h=0, string advisor=""); //constructor
    ~GraduateStudent(); //destructor
    string getAdvisor();
    void setAdvisor(string advisor);
    //Class overrides??

private:
    string Advisor;
}

Ученик класса был дан, я добавил производный от Аспиранта класс.

Мой вопрос первый, если я правильно настроил производный класс.Мой второй вопрос: как я могу переопределить функцию year без операторов if?Я пытался использовать эти утверждения, но редактор дал мне ошибки, я подозреваю, так как это заголовочный файл.

Ответы [ 5 ]

4 голосов
/ 11 октября 2011

Студенческий класс, который вам «дали», на самом деле написан неправильно, чтобы должным образом учесть переопределение функции года.Сценарий общего использования (когда вы удерживаете объекты ученика в контейнере, не будет работать должным образом).

Итак, чтобы исправить (правильно):

// Generally, poor practice to have a using namespace
// directive in a header file, instead just properly 
// scope your variables (as below)
// using namespace std;

class Student
{
public:
    Student( std::string s = "", int h = 0);

    // Virtual desctructors allow you to properly free derived
    // classes given a base class pointer
    virtual ~Student();

    std::string getName() const;
    int getHours() const;
    void setName(std::string s);
    void setHours (int h);

    // This function needs to be virtual to be overridable
    virtual std::string year () const;
private:
    std::string name;
    int hours;

};

// Use Public inheritance, after all a
// GraduateStudent IS-A Student
class GraduateStudent: public Student
{
public:
    GraduateStudent(std::string s = "", int h=0, string advisor=""); //constructor
    ~GraduateStudent(); //destructor
    std::string getAdvisor();
    void setAdvisor(string advisor);
    //Class overrides??

    // this function overrides the Student::year() function
    std::string year() const;

private:
    std::string Advisor;
}

Кроме того, как вы думаете, почемуВы обязаны реализовать функцию year() без использования операторов if?Это было бы уместно в этом случае.

4 голосов
/ 11 октября 2011

Если вы объявляете функцию с тем же именем в производном классе, она скрывает все функции с тем же именем в базовом классе.

Так что просто добавьте:

string year () const;

Чтобы ваш производный класс снова скрывал функцию базового класса.

Обратите внимание, что эта функция скрывает, а не переопределяет.Для переопределения вам нужно, чтобы функция была объявлена ​​как виртуальная в вашем базовом классе.И это то, о чем просит Q:

Ваш базовый класс должен иметь:

virtual string year () const;

Далее вы объявляете его в своем производном классе, а затем определяете его соответствующим образом.


Частное наследование не очень хорошая идея, потому что здесь,
При частном наследовании все члены базового класса становятся частными членами производного класса.

Приведенное выше правило будет означать, что вы не можете вызывать (для объекта класса Derived) ни один из методов, которые имеют реализацию только в базовом классе, и ни одного в классе Derived, это не то, что вы пытаетесь реализовать, я думаю.

3 голосов
/ 11 октября 2011

Чтобы переопределить функцию-член, вам нужно только предоставить объявление и определение в производном типе при условии , что функция является виртуальной.Вы не можете переопределить функцию в базовом классе, если она не является виртуальной.

Поскольку целью упражнения, вероятно, является использование GraduateStudent в качестве любого другого студента, вы, вероятно, захотите использоватьpublic наследование.Частное наследование обычно используется только для обеспечения , реализованного в терминах , а не is-a отношений.

Другие комментарии, которые приходят на ум при реализации классов:

  • Конструкторы должны быть явными, вам, вероятно, не нужны неявные преобразования из строк
  • Деструктор ученика должен быть виртуальным (или защищенным), чтобы избежать неопределенного поведения, если вы пытаетесь удалитьGraduateStudent через указатель на Student
  • Строки в установщиках, вероятно, лучше всего передавать с помощью константной ссылки - здесь может быть какое-то обсуждение, но за рамками вашего курса (то есть с новой семантикой перемещения), в зависимости от шаблона использования любой параметр может быть лучше / хуже.
  • Строки должны возвращаться в методах доступа по ссылке (без сомнения, в этом случае)
  • Операции, которые не изменяютсостояние объектов должно быть помечено const
0 голосов
/ 11 октября 2011

Сделать функцию виртуальной в базовом классе ученика virtual string year().Затем предоставьте новое определение в GraduateStudent, которое заменяет метод year тем, что вы хотите.

0 голосов
/ 11 октября 2011

Частное наследование от Студента ограничивает доступ к его функциям.В этом случае Public или Protected будут более полезными.

Объявление метода year как виртуального позволит вам реализовать его в классе GraduateStudent и вызвать его, если вы обращаетесь к классу как студент.

...