c++ - programacion - polimorfismo pdf
¿Por qué el enlazador ld permite múltiples definiciones de clase con los mismos métodos? (1)
Considere este archivo, first.cpp
, que contiene una definición de clase y use:
#include <iostream>
struct Foo
{
Foo(){ std::cout << "Foo()" << std::endl; }
~Foo(){ std::cout << "~Foo()" << std::endl; }
};
int main(){
Foo f;
return 0;
}
y otra, second.cpp
, que contiene una definición de clase conflictiva:
#include <iostream>
struct Foo
{
Foo();
~Foo();
};
Foo::~Foo(){ std::cout << "wrong ~Foo()" << std::endl; }
El vinculador se queja de los símbolos duplicados cuando hay dos funciones con los mismos nombres definidos, pero estos archivos con métodos de clase duplicados se compilan sin un error.
Compilé con estos comandos:
$ g++ -c second.cpp -o second
$ g++ second first.cpp -o first
Reordenar los argumentos a la segunda llamada de g++
no cambia la salida.
Y cuando se ejecuta por first
vez, esta es la salida:
$ ./first
Foo()
wrong ~Foo()
¿Por qué el enlazador permite métodos de clase duplicados? Si aparentemente está permitido, ¿por qué está wrong ~Foo()
impreso?
De nuevo, comportamiento indefinido. Su programa tiene múltiples definiciones para el destructor de Foo
, lo que significa que está en violación de la ODR. El programa está mal y cualquier cosa puede pasar.
¿Por qué el enlazador no lo recoge? Cuando se define una función dentro de la definición de clase, está implícitamente en inline
. Los compiladores generalmente marcan esas funciones como ''símbolos débiles''. El enlazador obtiene todas las unidades de traducción e intenta resolver los símbolos. El enlazador eliminará los símbolos débiles si es necesario (es decir, si el símbolo ya está definido en otro lugar).
A partir de la salida real del programa, parece que el compilador no alinea realmente la llamada al constructor y, por lo tanto, se envía en tiempo de ejecución al símbolo que dejó el vinculador (el no débil)
¿Por qué el enlazador permite tener métodos duplicados?
Porque todos (pero a lo sumo uno) son símbolos débiles (es decir, en inline
)
¿Por qué, en este caso, se imprime mal ~ Foo ()?
Debido a que la llamada no estaba en línea, y el enlazador soltó el símbolo débil