6 votes

Je pense que la déclaration ci-dessous est incorrecte ou j'ai raté quelque chose ?

Le paragraphe ci-dessous a été extrait de la page 420 du livre de Stroustup "The C++ Programming Language" (troisième édition) :

Parce qu'un pointeur vers un membre virtuel (s dans cet exemple) est une sorte de décalage, il ne dépend pas de l'emplacement d'un objet en mémoire. A pointeur vers un membre virtuel peut donc être transmis en toute sécurité entre différents espaces d'adressage, tant que la même disposition d'objet est utilisée en les deux. Comme les pointeurs vers les fonctions ordinaires, les pointeurs vers les fonctions membres non virtuelles ne peuvent pas être échangés entre les espaces d'adressage. ne peuvent pas être échangés entre espaces d'adressage.

Je conteste la dernière phrase de ce paragraphe. Ci-dessous, vous trouverez un extrait de code où les pointeurs sur non virtuelle les fonctions des membres, foo() y foo1() sont échangés entre un objet de base a et un objet dérivé b sans problème.

Ce qui ne peut pas être fait, c'est la surcharge de n'importe quelle fonction de la base, foo() o foo1() dans la classe dérivée, car dans ce cas, le compilateur émettra une erreur comme indiqué ci-dessous.

#include <iostream>

class A
{
    int i;
    public:
    A() : i(1) {}
    void foo() { std::cout << i << '\n'; }
    void foo1() { std::cout << 2 * i << '\n'; }
};

class B: public A
{
    int j;
    public:
    B() : A(), j(2) {}
//  void foo() { std::cout << j << '\n'; }
};

int main()
{
    typedef void (A::* PMF)();
    PMF p = &B::foo;    //   error C2374: 'p' redefinition, multiple initialization
                        //   if foo() is overloaded in B.
    PMF q = &B::foo1;
    B b;
    (b.*p)();
    (b.*q)();

    A a;
    (a.*p)();
    (a.*q)();
}

1voto

axxel Points 929

Cette phrase est correcte : En C++ (standard), un programme, ou plutôt un processus, a exactement un espace d'adressage. Donc, comme l'a souligné ulidtko, cette phrase fait référence aux possibilités d'échanger des pointeurs vers des fonctions membres virtuelles ou non entre les espaces d'adressage de différents processus.

A fonction membre non virtuelle d'une classe est en gros une fonction standard avec un argument implicite pour l'objet pour lequel vous l'appelez (l'élément ce pointeur). En tant que tel, il se voit attribuer une adresse dans l'espace d'adressage de votre processus lors du chargement. L'endroit exact où elle se retrouve dans votre espace d'adressage dépend certainement de votre plate-forme et du fait que cette fonction membre fasse ou non partie d'une bibliothèque liée dynamiquement. Le fait est que, pour deux processus, ce n'est pas nécessairement la même adresse. Ainsi, le fait de passer un pointeur à une telle fonction et de l'exécuter dans un autre processus peut potentiellement "mettre le feu à votre machine (TM)".

A fonction membre virtuelle est toujours plus ou moins la même chose que la fonction membre non virtuelle, comme dans "une adresse en mémoire à laquelle vous sautez lors de l'exécution et à laquelle vous passez ce pointeur", mais il est appelé par la table de fonction virtuelle (vtable) au lieu de directement. Ainsi, un pointeur vers une fonction membre virtuelle est en fait un index dans la table des fonctions virtuelles de votre objet. L'appel de cette fonction s'apparente alors à quelque chose du type "prendre le pointeur de votre objet, peut-être incrémenter le pointeur pour atteindre la table virtuelle de l'objet et sauter à l'adresse à l'index donné de cette table, en passant l'adresse de l'objet lui-même en tant qu'adresse de la fonction virtuelle". ce pointeur". Cette indirection via la table virtuelle permet donc d'échanger le pointeur vers la fonction membre virtuelle entre les espaces d'adressage.

Avertissement : Je dépasse quelque peu ma zone de confort "Je sais vraiment de quoi je parle". Donc, si j'ai trop simplifié quelque chose ou, pire encore, si je me suis engagé dans la distribution de fausses informations, n'hésitez pas à mettre ma réponse en pièces ;).

0voto

user2177829 Points 11

Un pointeur existera toujours en tant que mémoire virtuelle, c'est donc correct, vous pouvez vérifier l'adresse et vous verrez qu'il n'y a pas de pointeur physique à l'adresse de la mémoire.

Parce qu'un pointeur vers un membre virtuel (s dans cet exemple) est une sorte de décalage, il ne dépend pas de l'emplacement d'un objet en mémoire. Un pointeur vers un membre virtuel peut donc être transmis en toute sécurité entre différents espaces d'adressage tant que la même disposition d'objet est utilisée dans les deux. Comme les pointeurs vers les fonctions ordinaires, les pointeurs vers les fonctions membres non virtuelles ne peuvent pas être échangés entre les espaces d'adressage.

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