online c++ function inline member

online - inline function c++



Función miembro en línea de C++ en archivo.cpp (6)

Citando de las preguntas frecuentes de C ++ :

Nota: Es imperativo que la definición de la función (la parte entre {...}) se coloque en un archivo de encabezado, a menos que la función se use solo en un único archivo .cpp. En particular, si coloca la definición de la función en línea en un archivo .cpp y la llama desde algún otro archivo .cpp, obtendrá un error "no resuelto externo" del vinculador.

El compilador necesita ver la definición de la función en línea siempre que encuentre algún uso de esa función en línea. Normalmente, esto es posible si la función en línea se coloca en un archivo de encabezado.

¿El compilador en línea getA?

No, excepto cuando el uso de getA() está en B.cpp.

Si es así, ¿cuál palabra clave en línea es la más significativa (la del encabezado o la del cpp)?

Mejores prácticas : solo en la definición fuera del cuerpo de la clase.

¿Hay alguna otra manera de poner la definición de una función miembro en línea en su archivo cpp?

No, al menos no lo sé.

Sé que las funciones integradas del miembro por definición deberían ir al encabezado. Pero, ¿qué pasa si no es posible poner la implementación de la función en el encabezado? Tomemos esta situación:

Archivo Ah

#pragma once #include "B.h" class A{ B b; };

Archivo Bh

#pragma once class A; //forward declaration class B{ inline A getA(); };

Debido a la circular, tengo que poner la implementación de getA en

B.cpp

#include "B.h" #include "A.h" inline A B::getA(){ return A(); }

¿El compilador en línea getA ? De ser así, ¿qué palabra clave en línea es la más significativa (la del encabezado o la del archivo .cpp)? ¿Hay alguna otra manera de poner la definición de una función miembro en línea en su archivo .cpp?


En estos días, la mayoría de los compiladores pueden realizar inline en tiempo de enlace, así como tiempo de compilación. Si es probable que su función se beneficie de la creación, es probable que el Optimizador de tiempo de enlace haga precisamente eso.

Para cuando el enlazador llega, no hay mucho disponible sobre el estado en línea de la salida del compilador, excepto que el compilador indicará que ciertos objetos son coleccionables, por ejemplo, porque una función en línea o instancia de plantilla de clase aparece en varias unidades de compilación, o debería generar un error cuando varios símbolos comparten un nombre, como la función principal que se define dos veces. Nada de esto tiene influencia en el código real que generará.


Esta es la forma en que lo hice.

Archivo Ah

#pragma once #include "B.h" class A { B b; };

Archivo Bh

#pragma once class B { public: template<class T> inline T getA() { assert(NULL); // Use ''getA<A>()'' template specialization only! return NULL; } }; class A; // Forward declaration template<> inline A B::getA<A>();

Archivo Ch

#pragma once #include "A.h" #include "B.h" // Implement template specialization here! template<> inline A B::getA<A>() { return A(); }

Simplemente incluya el archivo "Ch" para poder usar el método getA (). El único cambio con el código original es que el método getA () debe definirse como público en lugar de privado.

Sin embargo, como muchos de ustedes lo explicaron, esto no es realmente útil.


ISO / IEC 14882: 2014

Cada programa debe contener exactamente una definición de cada función o variable no en línea que se utiliza en ese programa; no se requiere diagnóstico. La definición puede aparecer explícitamente en el programa, se puede encontrar en la biblioteca estándar o definida por el usuario, o (cuando corresponda) está implícitamente definida (ver 12.1, 12.4 y 12.8). Se debe definir una función en línea en cada unidad de traducción en la que se utiliza.


Me gustaría ir sobre esto desde la dirección opuesta.

No agregue declaraciones en línea a su función (a menos que también lo necesite).

La única vez que necesita agregar la declaración en línea a una función / método es si define la función en un archivo de encabezado pero fuera de la declaración de clase.

Xh

class X { public: int getX() { return 4;} // No inline because it is part of the class. // The compiler knows that needs an inline tag int getY(); int getZ(); }; inline int X::getY() { return 5;} // This needs to be explicitly declared inline. // Otherwise the linker will complain about // multiple definitions in compilation units.

X.cpp

// Never declare anything inline in the cpp file. int X::getZ() { return 6; }

Para ti caso más específico.
Elimine todas las especificaciones en línea. No están haciendo lo que crees que están haciendo.


No puede, fuera del alcance de B.cpp. El compilador opera en base a una unidad por compilación, es decir, compila cada archivo .cpp individualmente, de modo que si compila C.cpp, no tendrá disponible el código para getA () y deberá realizar una llamada de función y haz que el enlazador lo arregle (o, si realmente te tomó por la palabra e intentó alinearlo, habrá terminado con un error del enlazador. inline tiene cualidades similares a la static ).

La única excepción es LTCG, es decir, generación de código de tiempo de enlace, que está disponible en los compiladores más nuevos.

Un enfoque en este caso es tener otro archivo de encabezado (a veces denominado * .inl) que contenga el código en línea.

EDITAR: En cuanto a qué en línea es relevante, es el que está en la definición de la clase, es decir, en el archivo de encabezado. Tenga en cuenta que muchos compiladores tienen su propia opinión sobre lo que se puede y debe incluir. gcc, por ejemplo, puede desactivar la creación de líneas por completo (-O0), o puede alinear cualquier cosa que considere válida en línea (como -O3).