gpt4 book ai didi

c++ - 在 C++ 中链接 "static"方法时出现问题

转载 作者:可可西里 更新时间:2023-11-01 18:40:11 24 4
gpt4 key购买 nike

我想调用在不同文件中定义的 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 文件中并使用它。我错过了什么吗?

感谢您的帮助。

最佳答案

很明显,您具有 Java 背景,因为您还没有掌握头文件的概念。在 Java 中,定义某物的过程通常是一体的。您同时声明和定义。在 C/C++ 中,这是一个两步过程。 声明 一些东西告诉编译器“这个类型存在一些东西,但我稍后会告诉你它是如何实际实现的”。 定义 某些东西是给编译器实际的实现部分。头文件主要用于声明,.cpp 文件用于定义。

头文件用于描述类的“API”,而不是它们的实际代码。可以在 header 中包含代码,这称为 header 内联。你已经在 CppClass.cpp 中内联了所有内容(不好,标题内联应该是异常(exception)),然后你在 main.cpp 中再次声明你的类,这是 C++ 中的双重声明。每次使用方法时,类主体中的内联都会导致代码重复(这听起来很疯狂。有关详细信息,请参阅 C++ faq section on inlining。)

在代码中包含双重声明会导致编译器错误。将类代码留在外面进行编译,但会给您一个链接器错误,因为现在您在 main.cpp 中只有类似标题的类声明。链接器看不到实现您的类方法的代码,这就是出现错误的原因。与 Java 不同,C++ 链接器不会自动搜索它想要使用的目标文件。如果您使用类 XYZ 并且不给它 XYZ 的目标代码,它只会失败。

请看Wikipedia's header file articleHeader File Include Patterns (该链接也在维基百科文章的底部,包含更多示例)

简而言之:

为每个类生成一个 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
}

要将它们链接在一起,做一个

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

(只是 gcc 的一个例子)

关于c++ - 在 C++ 中链接 "static"方法时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/116687/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com