Cette question m'a été posée lorsque j'ai reçu un commentaire de révision de code disant que les fonctions virtuelles ne doivent pas être en ligne.
Je pensais que les fonctions virtuelles en ligne pourraient être utiles dans les scénarios où les fonctions sont appelées directement sur les objets. Mais le contre-argument qui m'est venu à l'esprit est le suivant : pourquoi voudrait-on définir des fonctions virtuelles et utiliser ensuite des objets pour appeler des méthodes ?
Est-il préférable de ne pas utiliser les fonctions virtuelles en ligne, puisqu'elles ne sont presque jamais développées de toute façon ?
Extrait de code que j'ai utilisé pour l'analyse :
class Temp
{
public:
virtual ~Temp()
{
}
virtual void myVirtualFunction() const
{
cout<<"Temp::myVirtualFunction"<<endl;
}
};
class TempDerived : public Temp
{
public:
void myVirtualFunction() const
{
cout<<"TempDerived::myVirtualFunction"<<endl;
}
};
int main(void)
{
TempDerived aDerivedObj;
//Compiler thinks it's safe to expand the virtual functions
aDerivedObj.myVirtualFunction();
//type of object Temp points to is always known;
//does compiler still expand virtual functions?
//I doubt compiler would be this much intelligent!
Temp* pTemp = &aDerivedObj;
pTemp->myVirtualFunction();
return 0;
}
1 votes
Envisagez de compiler un exemple avec les commutateurs dont vous avez besoin pour obtenir un listing assembleur, puis montrez à l'examinateur du code que le compilateur peut effectivement intégrer des fonctions virtuelles.
1 votes
Ce qui précède ne sera généralement pas inlined, car vous appelez une fonction virtuelle à l'aide de la classe de base. Bien que cela ne dépende que de l'intelligence du compilateur. S'il était capable de signaler que
pTemp->myVirtualFunction()
pourrait être résolu comme un appel non virtuel, il pourrait avoir inline cet appel. Cet appel référencé est inline par g++ 3.4.2 :TempDerived & pTemp = aDerivedObj; pTemp.myVirtualFunction();
Votre code ne l'est pas.1 votes
Une chose que gcc fait en fait est de comparer l'entrée de la table virtuelle à un symbole spécifique et ensuite d'utiliser une variante inlined dans une boucle si elle correspond. Ceci est particulièrement utile si la fonction inlined est vide et la boucle peut être éliminée dans ce cas.
1 votes
@doc Les compilateurs modernes s'efforcent de déterminer au moment de la compilation les valeurs possibles des pointeurs. La simple utilisation d'un pointeur n'est pas suffisante pour empêcher l'inlining à n'importe quel niveau d'optimisation significatif ; GCC effectue même des simplifications à l'optimisation zéro !