Проблема создания базового класса из конструктора подкласса

У меня 2 класса. Поскольку Доктор будет считаться Сотрудником, я должен использовать функции класса Сотрудника в классе Доктора. Единственная дополнительная вещь, которая есть у класса «Доктор», — это TITLE. По сути, я пытался отправить значение конструктору Doctor, установить заголовок, а затем отправить оставшееся значение классу Employee, однако я не смог. Это то, что я сделал до сих пор,

employee.h

#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class Employee {
private:
    int ID;
    char *firstname;
    char *lastname;
    int telno;
    char *adress;
    char *mail;
    int salary; 

public:
    Employee();
    Employee(int,char *,char*,int,char*,char*,int);

    char* getfmame();
    char* getlname();
    char* getadress();
    char* getmail();
    int getID();
    int gettel();
    int getsalary();
    void printall();
};
#endif

Employee.cpp

#include <iostream>
#include "employee.h"

using namespace std;
Employee::Employee() {
    firstname = "Empty";
    ID=0;
    firstname="Empty";
    lastname="Empty";
    telno=0;
    adress="Empty";
    mail="Empty";
    salary=0; 
}

Employee::Employee(int id,char * first,char* last,int tell,char* adres,char* email,int salar){
    ID=id;
    firstname=first;
    lastname=last;
    telno=tell;
    adress=adres;
    mail=email;
    salary=salar;

}
char* Employee::getfmame(){ return firstname; }
char* Employee::getlname(){ return lastname; }
char* Employee::getadress(){ return adress; }
char* Employee::getmail(){ return mail; }
int Employee::getID(){ return ID; }
int Employee::gettel(){ return telno; }
int Employee::getsalary(){ return salary; }

void Employee::printall(){
    cout<<endl<<"EMLOYEE INFORMATION"<<endl<<"------------------"<<endl;
    cout<<endl<<"ID :"<<ID<<endl<<"FIRST NAME: "<< firstname <<endl<<"LAST NAME: "<< lastname << endl << "TELEPHONE NUMBER: "<<telno<<endl<<"ADRESS: "<<adress<<endl<<"MAIL: "<<mail<<endl<<"SALARY: "<<salary<<endl;

}

Доктор.h

#ifndef DOCTOR_H
#define DOCTOR_H
#include "Employee.h"

using namespace std;
class Doctor :Employee {
public:
    enum title {Intern=0,Practitioner=1,Assistant=2,Specialist=3,Docent=4,Professor=5,None=6};
    Doctor();
    Doctor(title a,int id,char * first,char* last,int tell,char* adres,char* email,int salar);  
};
#endif

Доктор.cpp

#include <iostream>
#include "Doctor.h"
#include "Employee.h"

using namespace std;

Doctor::Doctor() {
    title tit = None ;
}

Doctor::Doctor(title a,int id,char * first,char* last,int tell,char* adres,char* email,int salar) {
    title tit=a;
    Employee(id,first,last, tell,adres,email,salar);
    printall();
    cout<<"typed";
}

Main.cpp

#include <iostream>
#include "employee.h"
#include "doctor.h"
using namespace std;

int main(){ 
    Doctor a=Doctor(Doctor::None,12,"a","b",0550550505,"8424 str nu:5","@hotmail",5000);
    return 0;
}

person Mert Özçelik    schedule 16.04.2020    source источник
comment
Какая у вас проблема?   -  person Barmar    schedule 17.04.2020
comment
У вас есть employee.h и Employee.h. В зависимости от операционной системы они могут не считаться одинаковыми.   -  person Barmar    schedule 17.04.2020
comment
Для части вашей проблемы, инициализируя Employee базовый класс Doctor, вам нужно будет использовать Список инициализаторов участников   -  person user4581301    schedule 17.04.2020
comment
Я вызываю конструктор Doctor, а в конструкторе Doctor я хочу вызвать класс Employee, чтобы зарегистрировать его. Он его не отправляет.   -  person Mert Özçelik    schedule 17.04.2020
comment
Я получаю ошибки, когда пытаюсь скомпилировать ваш код. Поскольку вы используете частное наследование, методы, унаследованные от Employee, становятся частными методами Doctor, поэтому вы не можете вызывать a.printall().   -  person Barmar    schedule 17.04.2020
comment
Вы не делаете этого, явно вызывая конструктор. Перейдите по ссылке, чтобы увидеть правильный способ сделать это.   -  person Barmar    schedule 17.04.2020
comment
Вы должны изучить, как работает наследование, используя абсолютно минимальное количество игрушечного кода, и обращаться к проекту с несколькими файлами только тогда, когда вы понимаете наследование.   -  person David Schwartz    schedule 17.04.2020


Ответы (1)


Конструкция подкласса в C++ работает так, что объект базового класса должен быть создан при выполнении тела конструктора подкласса:

class A {
    /* etc. etc. */ 
public:
    void do_stuff();
};

class B : public A {
    B() {
        // at this point, an A has already been constructed!
        A::do_stuff();
    }
};

Обратите внимание, что в этом примере, поскольку мы не выбрали явный конструктор для экземпляра A, будет использоваться конструктор по умолчанию, A::A(); и если этот конструктор недоступен - мы получаем ошибку компиляции. Тот факт, что был вызван конструктор для A, позволяет нам затем использовать методы класса A — как A::do_stuff() в приведенном выше примере.

Но как мы можем указать другой конструктор перед телом конструктора B? Или в вашем случае, как мы можем использовать соответствующий конструктор для Employee перед телом конструктора Doctor?

Ответ был предложен @user4581301: вам нужно использовать список инициализаторов участников< /сильный>. Инициализации/конструкции в этом списке выполняются перед телом и могут включать базовый класс. Я продемонстрирую на упрощенном примере. Предположим, что у Employee есть только идентификатор, а у Doctor есть только дополнительный заголовок.

class Employee {
protected:
    int id_;
public:
    Employee(int id) : id_(id) { };
    int id() const { return id_; }
};

class Doctor : public Employee {
protected:
    std::string title_;
public:
    Doctor(int id, std::string title) : Employee(id), title_(title) { };
    const std::string& title() const { return title_; }
};

Итак, когда создается Doctor, он строит свой базовый экземпляр Employee, используя полученный id. Тело конструктора используется для более сложного кода, помимо простой инициализации членов.


PS:

  1. Возможно, вы захотите инициализировать член title_ с помощью std::move(title), а не только title, подробности см. в этом вопросе.
  2. Это сбивает с толку, когда конструктор имеет более двух или трех параметров с совместимыми типами — пользователи, скорее всего, перепутают их друг с другом. Вы можете рассмотреть значения по умолчанию для большинства полей и установить их после построения или, альтернативно, используя шаблон построителя.
  3. адрес, с двумя д, не адрес.
  4. Если вы не планируете редактировать char* полей на месте, используйте const char *.
  5. Если бы вы написали свои классы, методы Doctor не имели бы доступа для записи к методам Employee; убедитесь, что это то, что вы намеревались.
  6. У меня есть и другие придирки, но я остановлюсь...
person einpoklum    schedule 16.04.2020