Pouvons-nous faire un constructeur de copie de classe virtuel en C++

Pouvons - nous rendre un constructeur de copie de classe virtuel en C++? Comment l'utiliser?

22
demandé sur Luchian Grigore 2012-03-27 16:24:22

6 réponses

Non, vous ne pouvez pas, les constructeurs ne peuvent pas être virtuels.

C++03 - 12.1 Constructeurs

4) Un constructeur ne doit pas être virtual (10.3) ou static (9.4). [...]

Si vous avez besoin de quelque chose comme ça, vous pouvez rechercher l'idiome du constructeur virtuel ici .

20
répondu Luchian Grigore 2015-06-08 14:23:37

Non, vous ne pouvez pas.

De plus, Tout le concept n'a pas de sens. Les fonctions virtuelles sont des fonctions qui sont distribué basé sur la valeur d'un objet (le type dynamique de l'objet). Lorsqu'un constructeur est appelé, l'objet n'a pas encore de valeur (car il n'a pas encore été construit). Par conséquent, aucune expédition virtuelle ne peut se produire.

Pensez-y. Quelle sémantique aurait un tel constructeur?

4
répondu Mankarse 2012-03-27 12:38:38

Non. C++ étant un langage typé statique, il n'a aucun sens pour le compilateur C++ de créer un objet polymorphiquement. Le compilateur doit connaître le type de classe pour créer l'objet. En d'autres termes, quel type d'objet à créer est une décision de compilation du point de vue du compilateur C++. Si nous rendons le constructeur virtuel, le compilateur signale une erreur.

1
répondu zsounder 2012-03-27 12:32:13

Vous ne pouvez pas car la mémoire est allouée avant que le constructeur ne soit appelé en fonction de la taille du nouveau type et non de l'opérande de copie. Et si cela fonctionnait, ce serait un cas particulier qui inversait le polymorphisme pour un certain nombre de constructions de langage.

Mais cela ne signifie pas que cela ne peut pas être fait avec un peu de magie C++. :)

Il y a quelques cas où c'est incroyablement utile, en sérialisant des classes non-POD par exemple. Cet exemple crée un constructeur de copie virtuelle qui fonctionne utilisation du placement Nouveau.

Avertissement: Ceci est un exemple qui peut aider certains utilisateurs avec des problèmes spécifiques. Ne faites pas cela dans le code à usage général. Il se bloque si la mémoire allouée pour la nouvelle classe est plus petite que la classe dérivée. Le meilleur (et le seul) moyen sûr d'utiliser ceci est si vous gérez votre propre mémoire de classe et utilisez le placement new.

class VirtualBase
{
public: 
    VirtualBase() {}
    virtual ~VirtualBase() {}

    VirtualBase(const VirtualBase& copy)
    {
        copy.VirtualPlacementCopyConstructor(this);
    }

    virtual void VirtualPlacementCopyConstructor(void*) const {}
};

class Derived :: public VirtualBase
{
public:
    ...

    Derived(const Derived& copy) : ... don't call baseclass and make an infinite loop
    {
    }

protected:
    void VirtualPlacementCopyConstructor(void* place) const
    {
        new (place) Derived(*this);
    }
};
1
répondu George Davison 2017-02-06 03:08:43

Jamais, ce ne sera pas possible en C++.

0
répondu 2012-03-27 12:30:41

Oui, vous pouvez créer un constructeur de copie virtuelle, mais vous ne pouvez pas créer de constructeur virtuel.

Raison:

Constructeur virtuel: - impossible car c++ est un langage de type statique et crée un constructeur en tant que compilateur virtuel afin de ne pas pouvoir décider quel type d'objet il et laisser l'ensemble du processus pour l'exécution en raison du mot-clé virtuel. Le compilateur doit connaître le type de classe pour créer l'objet. En d'autres termes, ce type d'objet à créer est un décision de compilation du point de vue du compilateur C++. Si nous rendons le constructeur virtuel, le compilateur signale une erreur.

Constructeur de copie virtuelle: - Oui Possible, envisagez l'application clip board. Une carte clip peut contenir différents types d'objets, et copier des objets à partir d'objets existants, les Colle Sur le canevas de l'application. Encore une fois, quel type d'objet à copier est une décision d'exécution. Constructeur de copie virtuelle comble le vide ici.

0
répondu Priyanka Soni 2018-07-11 11:01:03