在程序结束前调用的c ++析构函数

时间:2014-03-24 17:16:50

标签: c++ class destructor main

当我在VS2013中运行以下代码时:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Auteur {
public:
    Auteur(string n, bool p = false)
    : nom(n), prime(p)
    {}
    const string getNom(){
        return nom;
    }
    bool getPrix(){
    return prime;
    }
   //Auteur(const Auteur&) = delete;

private:
   string nom;
   bool prime;
   };
class Oeuvre{
public:
    Oeuvre(string t, Auteur &a, string lang)
    : titre(t), langue(lang), auteur(a)
    {}
     tring getTitre(){
    return titre;
     }
const Auteur & getAuteur(){
    return auteur;
     }
    string getLangue(){
    return langue;
     }
    void affiche(){
    cout << titre << " ," << auteur.getNom() << " en " << getLangue() << endl;
    }

   ~Oeuvre(){
    cout << "L'oeuvre " <<titre << ", " << auteur.getNom() << ", en " << langue     << " n'est plus disponible." << endl;
   }
   //Oeuvre(const Oeuvre&) = delete;
 private:
    string titre;
    Auteur &auteur;
string langue;
};

class Exemplaire{
public:
Exemplaire(Oeuvre & oeuvre)
    : oeuvre(oeuvre)
{
    Auteur a = oeuvre.getAuteur();
    cout << "Nouvel exemplaire de : " << oeuvre.getTitre() << ", " << a.getNom() <<" en " << oeuvre.getLangue() << endl;
}
Exemplaire(Exemplaire const& ex)
    : oeuvre(ex.oeuvre)
{
    Auteur a = oeuvre.getAuteur();
    cout << "Copie d'un exemplaire de : " << oeuvre.getTitre() << ", " << a.getNom() << ", en " << oeuvre.getLangue() << endl;
}
const Oeuvre & getOeuvre() const{
    return oeuvre;
}
void affiche(){
    Auteur a = oeuvre.getAuteur();
    cout << "Exemplaire de : " << oeuvre.getTitre() << ", " << a.getNom() << ", en " << oeuvre.getLangue() << endl;
}
~Exemplaire(){
    Auteur a = oeuvre.getAuteur();
    cout << "Un exemplaire de " << oeuvre.getTitre() << ", " << a.getNom() << ", en " << oeuvre.getLangue() << " a été jeté !" << endl;
 }

private:
Oeuvre  &oeuvre;
};
class Bibliotheque{
public:
Bibliotheque(string nom)
    : nom(nom)
{
    cout << "La bibliothèque " << nom << " est ouverte !" << endl;
}
string getNom(){
    return nom;
}
void stocker(Oeuvre &oeuvre, int n = 1)
{
    for (int i = 0; i < n; i++){
        exp.push_back(new Exemplaire(oeuvre));
    }
}
void lister_exemplaires(string langue = ""){
    int taille = exp.size();
    if (langue.empty() == true)
    {
        for (auto & ex : exp) {
            (*ex).affiche();
        }

    }
    else {
        for (int i(0); i<taille; i++)
        {
            Oeuvre o = exp[i]->getOeuvre();
            if (o.getLangue() == langue){
                exp[i]->affiche();
            }
        }
    }
}
int compter_exemplaires(Oeuvre ev){
    int ct = 0;
    for (auto &ex : exp) {
        Oeuvre ew = (*ex).getOeuvre();
        Auteur at = ew.getAuteur();
        Auteur a = ev.getAuteur();
        if (ew.getTitre() == ev.getTitre() && at.getNom() == a.getNom() && ew.getLangue() == ev.getLangue())
            ct++;
    }
    return ct;
}
void afficher_auteurs(bool b= false){
    for (auto & ex : exp)
    {
        Oeuvre ev = (*ex).getOeuvre();
        Auteur auteur = ev.getAuteur();
        string s = auteur.getNom();
        if (b){
            if (auteur.getPrix())
            cout << s << endl;
        }

    }

}
~Bibliotheque(){
    cout << "La bibliothèque " << getNom() << " ferme ses portes, \net détruit ses exemplaire :" << endl;
    int taille = exp.size();
    for (int i(0); i<taille; i++)
        delete exp[i];
}

 private:
string nom;
vector <Exemplaire *> exp;
 };


int main()
{
Auteur a1("Victor Hugo"),
    a2("Alexandre Dumas"),
    a3("Raymond Queneau", true);

Oeuvre o1("Les Misérables", a1, "français"),
    o2("L'Homme qui rit", a1, "français"),
    o3("Le Comte de Monte-Cristo", a2, "français"),
    o4("Zazie dans le métro", a3, "français"),
    o5("The Count of Monte-Cristo", a2, "anglais");

Bibliotheque biblio("municipale");
biblio.stocker(o1, 2);
biblio.stocker(o2);
biblio.stocker(o3, 3);
biblio.stocker(o4);
biblio.stocker(o5);

cout << "La bibliothèque " << biblio.getNom()
    << " offre les exemplaires suivants :" << endl;
biblio.lister_exemplaires();

const string langue("anglais");
cout << " Les exemplaires en " << langue << " sont :" << endl;
biblio.lister_exemplaires(langue);

cout << " Les auteurs à succès sont :" << endl;
biblio.afficher_auteurs(true);

cout << " Il y a " << biblio.compter_exemplaires(o3) << " exemplaires de "
    << o3.getTitre() << endl;

return 0;
}

我得到以下输出:

La bibliothÞque municipale est ouverte !
Nouvel exemplaire de : Les MisÚrables, Victor Hugo en franþais
Nouvel exemplaire de : Les MisÚrables, Victor Hugo en franþais
Nouvel exemplaire de : L'Homme qui rit, Victor Hugo en franþais
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas en franþais
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas en franþais
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas en franþais
Nouvel exemplaire de : Zazie dans le mÚtro, Raymond Queneau en franþais
Nouvel exemplaire de : The Count of Monte-Cristo, Alexandre Dumas en anglais
La bibliothÞque municipale offre les exemplaires suivants :
Exemplaire de : Les MisÚrables, Victor Hugo, en franþais
Exemplaire de : Les MisÚrables, Victor Hugo, en franþais
Exemplaire de : L'Homme qui rit, Victor Hugo, en franþais
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en franþais
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en franþais
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en franþais
Exemplaire de : Zazie dans le mÚtro, Raymond Queneau, en franþais
Exemplaire de : The Count of Monte-Cristo, Alexandre Dumas, en anglais
 Les exemplaires en anglais sont :
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre L'Homme qui rit, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Zazie dans le mÚtro, Raymond Queneau, en franþais n'est plus disponible.
Exemplaire de : The Count of Monte-Cristo, Alexandre Dumas, en anglais
L'oeuvre The Count of Monte-Cristo, Alexandre Dumas, en anglais n'est plus disponible.
 Les auteurs Ó succÞs sont :
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre L'Homme qui rit, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
Raymond Queneau
L'oeuvre Zazie dans le mÚtro, Raymond Queneau, en franþais n'est plus disponible.
L'oeuvre The Count of Monte-Cristo, Alexandre Dumas, en anglais n'est plus disponible.
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre L'Homme qui rit, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre Zazie dans le mÚtro, Raymond Queneau, en franþais n'est plus disponible.
L'oeuvre The Count of Monte-Cristo, Alexandre Dumas, en anglais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
 Il y a 3 exemplaires de Le Comte de Monte-Cristo
La bibliothÞque municipale ferme ses portes,
et dÚtruit ses exemplaire :
Un exemplaire de Les MisÚrables, Victor Hugo, en franþais a ÚtÚ jetÚ !
Un exemplaire de Les MisÚrables, Victor Hugo, en franþais a ÚtÚ jetÚ !
Un exemplaire de L'Homme qui rit, Victor Hugo, en franþais a ÚtÚ jetÚ !
Un exemplaire de Le Comte de Monte-Cristo, Alexandre Dumas, en franþais a ÚtÚ jetÚ !
Un exemplaire de Le Comte de Monte-Cristo, Alexandre Dumas, en franþais a ÚtÚ jetÚ !
Un exemplaire de Le Comte de Monte-Cristo, Alexandre Dumas, en franþais a ÚtÚ jetÚ !
Un exemplaire de Zazie dans le mÚtro, Raymond Queneau, en franþais a ÚtÚ jetÚ !
Un exemplaire de The Count of Monte-Cristo, Alexandre Dumas, en anglais a ÚtÚ jetÚ !
L'oeuvre The Count of Monte-Cristo, Alexandre Dumas, en anglais n'est plus disponible.
L'oeuvre Zazie dans le mÚtro, Raymond Queneau, en franþais n'est plus disponible.
L'oeuvre Le Comte de Monte-Cristo, Alexandre Dumas, en franþais n'est plus disponible.
L'oeuvre L'Homme qui rit, Victor Hugo, en franþais n'est plus disponible.
L'oeuvre Les MisÚrables, Victor Hugo, en franþais n'est plus disponible.

相反,我应该得到以下输出:

La bibliothèque municipale est ouverte !
Nouvel exemplaire de : Les Misérables, Victor Hugo, en français
Nouvel exemplaire de : Les Misérables, Victor Hugo, en français
Nouvel exemplaire de : L'Homme qui rit, Victor Hugo, en français
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Nouvel exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Nouvel exemplaire de : Zazie dans le métro, Raymond Queneau, en français
Nouvel exemplaire de : The Count of Monte-Cristo, Alexandre Dumas, en anglais
La bibliothèque municipale offre les exemplaires suivants :
Exemplaire de : Les Misérables, Victor Hugo, en français
Exemplaire de : Les Misérables, Victor Hugo, en français
Exemplaire de : L'Homme qui rit, Victor Hugo, en français
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Exemplaire de : Le Comte de Monte-Cristo, Alexandre Dumas, en français
Exemplaire de : Zazie dans le métro, Raymond Queneau, en français
Exemplaire de : The Count of Monte-Cristo, Alexandre Dumas, en anglais
 Les exemplaires en anglais sont :
Exemplaire de : The Count of Monte-Cristo, Alexandre Dumas, en anglais
 Les auteurs à succès sont :
Raymond Queneau
 Il y a 3 exemplaires de Le Comte de Monte-Cristo
La bibliothèque municipale ferme ses portes,
et détruit ses exemplaires : 
Un exemplaire de "Les Misérables, Victor Hugo, en français" a été jeté !
Un exemplaire de "Les Misérables, Victor Hugo, en français" a été jeté !
Un exemplaire de "L'Homme qui rit, Victor Hugo, en français" a été jeté !
Un exemplaire de "Le Comte de Monte-Cristo, Alexandre Dumas, en français" a été jeté !
Un exemplaire de "Le Comte de Monte-Cristo, Alexandre Dumas, en français" a été jeté !
Un exemplaire de "Le Comte de Monte-Cristo, Alexandre Dumas, en français" a été jeté !
Un exemplaire de "Zazie dans le métro, Raymond Queneau, en français" a été jeté !
Un exemplaire de "The Count of Monte-Cristo, Alexandre Dumas, en anglais" a été jeté !
L'oeuvre "The Count of Monte-Cristo, Alexandre Dumas, en anglais" n'est plus disponible.
L'oeuvre "Zazie dans le métro, Raymond Queneau, en français" n'est plus disponible.
L'oeuvre "Le Comte de Monte-Cristo, Alexandre Dumas, en français" n'est plus disponible.
L'oeuvre "L'Homme qui rit, Victor Hugo, en français" n'est plus disponible.
L'oeuvre "Les Misérables, Victor Hugo, en français" n'est plus disponible.

你能告诉我究竟是什么问题。为什么在主程序结束之前调用Oeuvre类析构函数?

3 个答案:

答案 0 :(得分:1)

在'afficher_auteurs','compter_exemplaires'等循环中,你正在复制对象,就像这样;

 Oeuvre ev = (*ex).getOeuvre();

所以当getOeuvre通过引用返回对象时,接收器变量'ev'没有通过引用接收它,因此进行了复制。这些复制对象的析构函数将在循环退出时调用(当它超出范围时) - 这可能可能是你在'main'完成之前看到析构函数运行的原因

尝试修复此问题,将代码更改为通过引用接收,看看是否有效,如下所示;

  

全部作品&安培; ev =(* ex).getOeuvre();

  

const Oeuvre&amp; ev =(* ex).getOeuvre();

当你在这里时,你可能想要将所有你在Oeuvre上的方法声明为'const',比如

  

const Auteur&amp; getAuteur() const {....

因为否则你将无法在const对象上使用这些方法。

答案 1 :(得分:1)

您正在查看的Oeuvre类的析构函数不是直接在int main中初始化的任何变量(例如,o1,o2等);它适用于程序中其他地方使用的临时变量。

例如:

void afficher_auteurs(bool b= false){
for (auto & ex : exp)
{
    // **This is a temporary Oeuvre**
    Oeuvre ev = (*ex).getOeuvre();

    Auteur auteur = ev.getAuteur();
    string s = auteur.getNom();
    if (b){
        if (auteur.getPrix())
        cout << s << endl;
    }

} // **The temporary Oeuvre is destroyed here**

在程序结束之前调用析构函数并不罕见。每当一个对象被销毁时都会调用析构函数。

自动分配的变量(即堆栈上的变量)在超出范围时会自动销毁。

动态分配的变量(例如,使用new)在显式解除分配时会被销毁(例如,使用delete)。

答案 2 :(得分:0)

问题在于:

void lister_exemplaires(string langue = ""){
  int taille = exp.size();
  if (langue.empty() == true)
  {
    for (auto & ex : exp) {
        (*ex).affiche();
    }

  }
  else {
    for (int i(0); i<taille; i++)
    {
        /************************/
        Oeuvre o = exp[i]->getOeuvre();
        if (o.getLangue() == langue){
            exp[i]->affiche();
        }
        /************************/
    }
  }
}

你得到全部作品并制作本地副本。当for循环结束时,这个临时对象被销毁并且它的析构函数被调用。

改为使用引用:

const Oeuvre &o = exp[i]->getOeuvre();
//... as before