Quiero llamar a un par de «estática» de los métodos de una CPP clase definida en un archivo diferente, pero estoy teniendo problemas de enlazado. He creado un caso de prueba que recrea mi problema y el código que está a continuación.

(Soy completamente nuevo en C++, yo vengo de una Java de fondo y estoy un poco familiarizado con la C.)

//CppClass.cpp
#include <iostream>
#include <pthread.h>
static pthread_t thread;
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static int shutdown;
using namespace std;
class CppClass
{
public:
static void Start()
{
cout << "Testing start function." << endl;
shutdown = 0;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&thread, &attr, run_thread, NULL);
}
static void Stop()
{
pthread_mutex_lock(&mutex);
shutdown = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
static void Join()
{
pthread_join(thread, NULL);
}
private:
static void *run_thread(void *pthread_args)
{
CppClass *obj = new CppClass();
pthread_mutex_lock(&mutex);
while (shutdown == 0)
{
struct timespec ts;
ts.tv_sec = time(NULL) + 3;
pthread_cond_timedwait(&cond, &mutex, &ts);
if (shutdown)
{
break;
}
obj->display();
}
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_exit(NULL);
return NULL;
}
void display()
{
cout << " Inside display() " << endl;
}
};
//main.cpp
#include <iostream>
/* 
* If I remove the comment below and delete the
* the class declaration part, it works.
*/
//#include "CppClass.cpp"
using namespace std;
class CppClass
{
public:
static void Start();
static void Stop();
static void Join();
};
int main()
{
CppClass::Start();
while (1)
{
int quit;
cout << "Do you want to end?: (0 = stay, 1 = quit) ";
cin >> quit;
cout << "Input: " << quit << endl;
if (quit)
{
CppClass::Stop();
cout << "Joining CppClass..." << endl;
CppClass::Join();
break;
}
}
}

Cuando traté de compilar me sale el siguiente error:

$ g++ -o ir main.cpp CppClass.cpp -l pthread 
/tmp/cclhBttM.o(.texto+0x119): En la función `main': 
: undefined reference to `CppClass::Start()' 
/tmp/cclhBttM.o(.texto+0x182): En la función `main': 
: undefined reference to `CppClass::Stop()' 
/tmp/cclhBttM.o(.texto+0x1ad): En la función `main': 
: undefined reference to `CppClass::Join()' 
collect2: ld devuelto 1 estado de salida 

Pero si puedo quitar de la declaración de clase en main.cpp y reemplazarlo con #include «CppClass.cpp» funciona bien. Básicamente, quiero poner estas declaraciones en una por separado .h archivo y utilizarlo. Me estoy perdiendo algo?

Gracias por la ayuda.

Por favor, poner el código dentro de un <pre> bloquear

OriginalEl autor Srikanth | 2008-09-22

5 Comentarios

  1. 31

    Es obvio que provienen de una Java de fondo porque no se ha comprendido el concepto de archivos de encabezado. En Java el proceso de definición de algo es por lo general en una sola pieza. Usted declara y define al mismo tiempo. En C/C++ es un proceso de dos pasos. Declarar algo le dice al compilador de «algo que existe con este tipo, pero te diré más adelante, cómo está implementada en la realidad». La definición de algo que está dando el compilador de la implementación real de la parte. Archivos de encabezado se utiliza sobre todo para las declaraciones .archivos cpp para las definiciones.

    Encabezado de los archivos están allí para describir la «API» de las clases, pero no su código real. Es posible incluir código en el encabezado, que se llama en el encabezado de inline. Tiene entre líneas todo lo que en CppClass.cpp (no es bueno, en el encabezado de inline debe ser la excepción) y, a continuación, se declara la clase en main.cpp de NUEVO, lo que es una doble declaración en C++. El inline en el cuerpo de la clase lleva a código reduplication cada vez que utilice un método (esto sólo sonidos loco. Ver el C++ sección de preguntas frecuentes en inline para más detalles.)

    Incluyendo la doble declaración en el código da un error del compilador. Salir de la clase de código compila, pero da un error del vinculador porque ahora sólo tiene el encabezado-como la declaración de la clase en main.cpp. El vinculador no ve el código que implementa la clase de métodos, es por eso que los errores aparecen. Diferentes a Java, C++ vinculador NO busque automáticamente los archivos objeto que se quiere utilizar. Si utiliza la clase XYZ y no le dan el código objeto para XYZ, simplemente no.

    Por favor, eche un vistazo a Wikipedia archivo de encabezado del artículo y Archivo De Encabezado Incluir Patrones (el enlace está también en la parte inferior del artículo de Wikipedia y contiene más ejemplos)

    En resumen:

    Para cada clase, generar un NewClass.h y NewClass.cpp archivo.

    En el NewClass.h archivo, escriba a:

    class NewClass {
    public:
    NewClass();
    int methodA();
    int methodB();
    }; <- don't forget the semicolon

    En el NewClass.cpp de archivo, escriba a:

    #include "NewClass.h"
    NewClass::NewClass() {
    //constructor goes here
    }
    int NewClass::methodA() {
    //methodA goes here
    return 0;
    }
    int NewClass::methodB() {
    //methodB goes here
    return 1;
    }

    En main.cpp, escribe:

    #include "NewClass.h"
    int main() {
    NewClass nc;
    //do something with nc
    }

    De vincular todos juntos, hacer un

    g++ -o NewClassExe NewClass.cpp main.cpp

    (sólo un ejemplo con gcc)

    usted debe marcar esta la respuesta.
    Gracias a todos. @Ben: yo lo hice.

    OriginalEl autor

  2. 9

    Se está definiendo la clase dos veces, que estoy bastante seguro de que no funciona.

    Intentar algo como esto:

    Primero un encabezado CppClass.h archivo:

    //CppClass.h
    using namespace std;
    class CppClass
    {
    public:
    static void Start();
    static void Stop();
    static void Join();
    private:
    void *run_thread(void *pthread_args);
    void display();
    };

    A continuación, un CppClass.cpp archivo de la aplicación:

    //CppClass.cpp
    #include <iostream>
    #include <pthread.h>
    #include "CppClass.h"
    using namespace std;
    void CppClass::Start()
    {
    /* method body goes here */
    }
    void CppClass::Stop()
    {
    /* method body goes here */
    }
    void CppClass::Join()
    {
    /* method body goes here */
    }
    void *CppClass::run_thread(void *pthread_args)
    {
    /* method body goes here */
    }
    void CppClass::display() {
    /* method body goes here */
    }

    Entonces su archivo principal:

    //main.cpp
    #include "CppClass.h"
    int main()
    {
    /* main method body here */
    }

    Creo que el g++ llamada sería el mismo.

    Básicamente, usted no puede declarar la misma clase dos veces. Usted debería declarar la clase en el archivo de encabezado, luego de declarar la aplicación en el archivo cpp. También podría poner todo el código en línea en un solo declaración de la clase en un archivo de encabezado. Pero declarar dos veces como usted hizo no funciona.

    Espero que tenía sentido…

    OriginalEl autor Herms

  3. 2

    Creo que quiere hacer algo como:

    g++ -c CppClass.cpp
    g++ -c main.cpp
    g++ -o vaya principal.o CppClass.o

    Que debe resolver.

    OriginalEl autor Jon

  4. 1

    hacer una .h archivo con la definición de la clase y, a continuación, #incluir ese archivo en su 2 archivos.

    OriginalEl autor Greg Rogers

  5. 0

    Claro que se ve como el vinculador no está recogiendo en segundo lugar el archivo de origen.

    OriginalEl autor Benoit

Dejar respuesta

Please enter your comment!
Please enter your name here