在C题链接“静态”的方法++(Problem Linking “static” Methods in

2019-09-20 06:23发布

我想打电话给在不同的文件中定义的CPP类的一些“静态”的方法,但我在链接的问题。 我创建,再现我的问题,它的代码是低于测试用例。

(我完全新的C ++,我来自一个Java的背景,我有点熟悉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;
                }
        }
}

当我试图编译,我得到以下错误:

$ g++ -o go main.cpp CppClass.cpp -l pthread
/tmp/cclhBttM.o(.text+0x119): In function `main':
: undefined reference to `CppClass::Start()'
/tmp/cclhBttM.o(.text+0x182): In function `main':
: undefined reference to `CppClass::Stop()'
/tmp/cclhBttM.o(.text+0x1ad): In function `main':
: undefined reference to `CppClass::Join()'
collect2: ld returned 1 exit status

但是,如果我删除的main.cpp类的声明,并用#include替换为“CppClass.cpp”,它工作正常。 基本上,我希望把这些声明在一个单独的.h文件中,并使用它。 我缺少的东西吗?

谢谢您的帮助。

Answer 1:

很明显你来自一个Java的背景,因为你还没有掌握的头文件的概念。 在Java中定义的东西的过程通常是在一块。 您声明,并在同一时间定义。 在C / C ++它是一个两步过程。 声明的东西告诉编译器“这种类型的东西存在,但后来它实际上是如何实现的,我会告诉你。” 定义什么是让编译器实际执行部分。 头文件大多用于对定义的声明,.cpp文件。

头文件是否有描述类的“API”,但不是他们的实际代码。 这可能包括在标题中,这就是所谓的头,内联代码。 你已经在联一切CppClass.cpp(不好,头,内联应该是例外),然后你在main.cpp中再次声明你的类,这是一个在C双声明++。 在类体内的内联导致每次你使用的方法编写加倍(这只是听起来很疯狂。参见上内联C ++ FAQ部分了解详情。)

包括在你的代码双重申报给你一个编译器错误。 离开类代码编译出来,但给你一个链接错误,因为现在你只需要在main.cpp中头状类的声明。 链接器认为没有代码,实现你的类的方法,这就是为什么出现错误。 不同与Java,C ++的连接器将不会为对象自动搜索文件就是了使用。 如果您使用类某某,不给它的对象为XYZ代码,它只会失败。

请看看维基百科的头文件的文章和头文件包含模式 (链接也是在维基百科文章的底部,并包含更多的例子)

简而言之:

对于每个类,生成NewClass.h和NewClass.cpp文件。

在NewClass.h文件,写入:

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

在NewClass.cpp文件,写入:

#include "NewClass.h"

NewClass::NewClass() {
  // constructor goes here
}

int NewClass::methodA() {
  // methodA goes here
  return 0;
}

int NewClass::methodB() {
  // methodB goes here
  return 1;
}

在main.cpp中,写:

#include "NewClass.h"

int main() {
  NewClass nc;
  // do something with nc
}

以连接在一起这一切,做一个

克++ -o NewClassExe NewClass.cpp的main.cpp

(只是用gcc一个例子)



Answer 2:

你定义的类两次,我敢肯定是行不通的。

尝试是这样的:

第一头CppClass.h文件:

// 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();
};

然后,CppClass.cpp文件实现它:

// 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 */
}

然后你的主文件:

// main.cpp
#include "CppClass.h"

int main()
{
    /* main method body here */
}

我相信G ++调用将是相同的。

基本上,你不能宣布同一个类两次。 你应该声明类在头文件,然后在声明cpp文件的执行情况。 你也可以把所有的代码内嵌在类的单个声明在头文件。 但在宣布两次像你这样是行不通的。

我希望这是有道理的...



Answer 3:

我想你想要做的事,如:

G ++ -c CppClass.cpp G ++ -c main.cpp中的g ++ -o去main.o CppClass.o

这应该解决这个问题。



Answer 4:

使与类定义.h文件中,然后#包括该文件到您的2个文件。



Answer 5:

当然貌似链接器不会拿起你第二个源文件。



文章来源: Problem Linking “static” Methods in C++
标签: c++ linker g++