Supponiamo che abbiamo una base class A
:La regola dei tre/cinque si applica all'ereditarietà e ai distruttori virtuali?
class A {
public:
void SetName(const std::string& newName) {
m_name=newName;
}
void Print() const {
std::printf("A::Print(). Name: %s\n",m_name.c_str());
}
private:
std::string m_name;
};
Vogliamo estendere questa classe con class B
in modo da aggiungiamo il nostro distruttore virtuale, modificare un membro per virtual
e cambiare private
-protected
per inh:
class A {
public:
virtual ~A() {}
void SetName(const std::string& newName) {
m_name=newName;
}
virtual void Print() const {
std::printf("A::Print(). Name: %s\n",m_name.c_str());
}
protected:
std::string m_name;
};
class B : public A {
public:
virtual void Print() const {
std::printf("B::Print(). Name: %s\n",m_name.c_str());
}
};
Ora, poiché abbiamo aggiunto un distruttore in class A
abbiamo bisogno di creare un costruttore di copia e copia operatore in questo modo?
class A {
public:
virtual ~A() {}
A() = default;
A(const A& copyFrom){
*this = copyFrom;
}
virtual A& operator=(const A& copyFrom){
m_name=copyFrom.m_name;
return *this;
};
void SetName(const std::string& newName) {
m_name=newName;
}
virtual void Print() const {
std::printf("A::Print(). Name: %s\n",m_name.c_str());
}
protected:
std::string m_name;
};
A me questo sembra inutile come l'operatore di copia di default e costruttore di copia avrebbe fatto la stessa cosa.
@MarcoA. Il distruttore di una classe derivata potrebbe dover fare qualcosa in più e il distruttore della classe base deve essere virtuale se si desidera eliminare un derivato da un puntatore alla base. –
@Angew questa è una buona ragione. Right –
Nota: evitare di utilizzare i membri di dati 'protected' in generale; perché, a meno che non controlli strettamente la gerarchia dell'ereditarietà ('finale'), hai perso tutte le garanzie sullo stato di questo membro in generale. Questo è simile alla restituzione di un riferimento non const. –