С++ Аннотация Класс: конструктор да или нет?
Класс с одной (или более) виртуальными чистыми функциями является абстрактным и не может использоваться для создания нового объекта, поэтому он не имеет конструктора.
Теперь я читаю книгу, которая делает следующий пример:
class Employee {
public:
Employee(const char*, const char*);
~Employee();
const char* getFirstName() const;
const char* getLastName() const;
virtual double earnings() const=0 // pure virtual => abstract class
virtual void print() const
private:
char* firstName, lastName;
};
Если класс абстрактный, у нас есть конструктор? Он использует этот класс позже (Boss является общедоступным из Employee):
void Boss::Boss (const char* first, const char* last, double s)
: Employee (first, last)
Я немного смущен... спасибо заранее
Ответы
Ответ 1
Вы правы, когда говорите, что класс с чистой виртуальной функцией является абстрактным и не может быть создан. Но вы ошибаетесь, когда говорите, что у него не может быть конструктора.
Действительно, как показывает ваш пример, абстрактный класс может иметь частных членов, которые могут использоваться функциями-членами этого класса. И эти члены должны быть инициализированы. Конструктор - это способ сделать это (например, с помощью списка инициализации в производном классе, как показывает ваш второй пример), лучше, на мой взгляд, чем функция init()
, например.
Редактирование моего комментария в ответе: абстрактный класс может иметь переменные-члены и потенциально не виртуальные функции-члены, поэтому каждый производный класс из первого реализует определенные функции.
Тогда ответственность за инициализацию этих переменных-членов может принадлежать абстрактному классу (по крайней мере, всегда для частных членов, поскольку производный класс не сможет их инициализировать, но может использовать некоторые унаследованные функции-члены, которые могут использовать/полагаться на этих членов). Таким образом, для абстрактных классов идеально подходит для реализации конструкторов.
Ответ 2
Класс с чистой виртуальной функцией не может быть создан. Ожидается, что у него будут подклассы, которые расширят его и предоставят недостающую функциональность.
Эти подклассы будут строить базовый класс при их создании, они вызовут конструктор своего суперкласса, поэтому абстрактные классы имеют конструкторы в С++.
Таким образом, вы не можете создать экземпляр напрямую и вызвать конструктор напрямую, но будущие подклассы будут.
Ответ 3
В классе Employee
есть данные, и эти данные необходимо каким-то образом инициализировать. Конструктор - хороший способ сделать это.
Ответ 4
Если базовый абстрактный класс не имеет конструктора, как бы вы назначали значения членам firstname , lastname
для любого производного класса, когда вы создаете объект производного класса?
Предположим, что существует Manager Class
, полученный из Employee
, который добавляет данные Salary
и реализует earning()
. Теперь Employee
является абстрактным классом, но Manager
является concrete class
и, следовательно, вы можете иметь объект Manager
. Но когда вы создаете экземпляр Manager
, вам нужно инициализировать/назначать значения членам, унаследованным от base class i.e. Employee
. Один из способов состоит в том, что для этой цели у вас может быть setFirstName() & setLastName()
в базовом классе, и вы можете использовать их в конструкторе для derived class i.e. Manager
или более удобным способом было бы иметь конструктор в base abstract class Employee
.
Смотрите код ниже:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Employee {
public:
Employee(const char*, const char*);
~Employee();
const char* getFirstName() const;
const char* getLastName() const;
virtual double earnings() const=0; // pure virtual => abstract class
virtual void print() const;
private:
char* firstname;
char* lastname;
};
Employee::Employee(const char* first, const char* last){
firstname= (char*) malloc((strlen(first)+1)*sizeof(char));
lastname= (char*) malloc((strlen(last)+1)*sizeof(char));
strcpy(firstname,first);
strcpy(lastname,last);
}
Employee::~Employee(){
free(firstname);
free(lastname);
cout << "Employee destructed" << endl;
}
const char* Employee::getFirstName() const{ return firstname;}
const char* Employee::getLastName() const{ return lastname; }
void Employee::print() const{
cout << "Name: " << getFirstName() << " " << getLastName() << endl;
}
class Manager:public Employee{
public:
Manager(char* firstname,char* lastname,double salary):
Employee(firstname,lastname),salary(salary){}
~Manager(){}
double earnings() const {return salary;}
private:
double salary;
};
int main(){
Manager Object("Andrew","Thomas",23000);
Object.print();
cout << " has Salary : " << Object.earnings() << endl;
return 0;
}
Ответ 5
firstName и lastName являются частными членами, недоступными для Boss. Весь интерфейс к ним должен присутствовать в классе Employee, включая инициализацию.
Ответ 6
Инициализировать firstName и lastName. В противном случае вам придется написать код, чтобы инициализировать их в конструкторах каждого производного класса
Ответ 7
"Абстрактный класс содержит по крайней мере одну чистую виртуальную функцию. Вы объявляете чистую виртуальную функцию, используя чистый спецификатор (= 0) в объявлении виртуальной функции-члена в объявлении класса."
о
void Boss::Boss (const char* first, const char* last, double s)
: Employee (first, last)
first
и last
определены в базовом классе, поэтому для их инициализации нам нужно сделать вызов конструктору базового класса : Employee (first, last)
Ответ 8
Цель абстрактного класса состоит в том, что вы хотите расширить некоторые функции производными классами. Может ли он иметь конструктор? Да, это возможно, и целью является инициализация локальных переменных из базового класса. Вам следует избегать использования публичного конструктора в Abstract и использовать только защищенные.
Пример, который у вас есть, не является хорошим примером. Не знаю, что это за книга, но что плохой пример. Его как определение переменной int с именем переменной "iAmString":).
int iAmString = 12;
Приветствия