2 votes

Comment peut-on créer un objet sans appeler le constructeur en C++ ?

Le programme suivant est composé de 5 fichiers. La sortie est 0 32, au lieu de 14 32 et donc un objet est construit sans appeler le constructeur. Comment cela est-il possible ?

caractère.h :

#ifndef CHARACTER_H
#define CHARACTER_H 

class Character
{
public:
    Character() {}

    class Settings
    {
    public:
        int size_;
        Settings():
            size_(14)
        {}
    };
    const static Settings DEFAULT_SETTINGS;
};

#endif // CHARACTER_H

character.cpp :

#include "character.h"

const Character::Settings Character::DEFAULT_SETTINGS;

word.h

#ifndef WORD_H
#define WORD_H

#include <iostream>

#include "character.h"

class Word 
{
public:
    Word() {}

    class Settings
    {
    public:
        Character::Settings characterSettings_;
        int length_;

        Settings():
            length_(32)
        {
            characterSettings_ = Character::DEFAULT_SETTINGS;
        }
    };

    static const Settings DEFAULT_SETTINGS;

    void write(Settings settings = DEFAULT_SETTINGS) // this default parameter is 
                                                     // constructed without a   
                                                     // constructor call
    {
        std::cout << settings.characterSettings_.size_ << std::endl;
        std::cout << settings.length_ << std::endl;
     }
 };

#endif // WORD_H

word.cpp

#include "word.h"

const Word::Settings Word::DEFAULT_SETTINGS;

main.cpp

#include "word.h"

int main(int argc, char *argv[])
{
    Word member;
    member.write();
    return 1;
}

6voto

C'est ce qu'on appelle le fiasco de l'initialisation statique . En principe, il n'existe pas d'ordre fixe pour l'exécution des constructeurs de variables à durée statique définies dans différentes unités de traduction. Dans ce cas particulier, les Word::DEFAULT_SETTINGS a été construit avant le Character::DEFAULT_SETTINGS et a donc lu le 0 que les variables de durée statique ont avant d'être réellement initialisées. Si vous voulez voir quelque chose d'intéressant, videz le contenu du fichier Character::DEFAULT_SETTINGS et vous verrez que étrangement c'est suffisant 14

1voto

Kaz Points 18072

Le problème de l'ordre d'initialisation statique peut être résolu grâce à quelques astuces (pas vraiment) du fichier d'en-tête.

L'essentiel de l'idée est la suivante (et je l'ai mise en pratique plusieurs fois, mais il y a des lustres, donc ce n'est pas juste une idée en l'air sur Stack Overflow) :

Fondamentalement, vous mettez la définition de l'objet statique, comme foo_class g_foo; dans une zone spécialement délimitée de votre foo.h fichier d'en-tête :

#ifndef FOO_H
#define FOO_H

#include "bar.h"  // dependency: crucial part!

// ... declares foo_class ...

// foo is a client of bar

// Now somewhere near the bottom:

#ifdef DEFINE_GLOBAL_SINGLETONS
foo_class g_foo;
#endif

Maintenant, vous configurez un fichier source de dépôt singleton spécialement désigné, où vous incluez tous les en-têtes.

// singletons.cc
#define DEFINE_GLOBAL_SINGLETONS
#include "foo.h"
#include "bar.h"  // note deliberately wrong order!

Les dépendances et les gardes d'inclusion du fichier d'en-tête feront en sorte que les en-têtes soient inclus dans l'ordre des dépendances du module, et donc que le module DEFINE_GLOBAL_SINGLETONS les sections à ajouter à l'unité de traduction dans l'ordre approprié.

Dans une même unité de traduction, le C++ exige que les objets soient construits de haut en bas.

Vous obtenez donc un ordre d'initialisation des modules semblable à celui d'Ada/Modula : le module utilisé avant l'utilisateur. foo utilisateurs bar et donc le bar s'il y en a un, est initialisé avant que l'élément foo un.

Maintenant, l'inconvénient : recompiler le référentiel singleton à chaque fois qu'un en-tête change.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X