问题链接“静态” C ++中的方法 [英] Problem Linking "static" Methods in C++

查看:135
本文介绍了问题链接“静态” C ++中的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想调用一个在不同文件中定义的CPP类的几个静态方法,但我有链接问题。我创建了一个重新创建我的问题的测试用例,它的代码如下。



(我完全是新的C ++,我来自Java背景和

  // 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< 测试启动功能。 << 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>
/ *
*如果我删除下面的注释并删除
*类声明部分,它的工作原理。
* /
// #includeCppClass.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<< 你想结束吗?:(0 = stay,1 = quit);
cin>>放弃;
cout< 输入:<退出<< endl
if(quit)
{
CppClass :: Stop();
cout<< 加入CppClass ...< endl
CppClass :: Join();
break;
}
}
}



当我尝试编译时,我收到以下错误:

 
$ g ++ -o go main.cpp CppClass.cpp -l pthread
/ tmp / cclhBttM .o(.text + 0x119):在函数`main'中:
:未定义对`CppClass :: Start()'的引用
/tmp/cclhBttM.o(.text+0x182) `main':
:undefined对`CppClass :: Stop()'的引用
/tmp/cclhBttM.o(.text+0x1ad):在函数`main'中:
:undefined 'CppClass :: Join()'
collect2:ld返回1退出状态

但是如果我删除类声明main.cpp并替换为#includeCppClass.cpp,它工作正常。基本上,我想把这些声明在一个单独的.h文件,并使用它。



感谢您的帮助。

解决方案

很明显你来自Java背景,因为你还没有掌握头文件的概念。在Java中,定义东西的过程通常是一块。您同时声明和定义。在C / C ++中,它是一个两个步骤的过程。 声明某些内容告诉编译器此类型存在,但稍后我会告诉您它实际实现的方式。 定义是为编译器提供实际的实现部分。头文件主要用于声明,.cpp文件用于定义。



头文件用于描述类的API,但不是它们的实际代码。可以在标题中包含代码,称为标题内联。你已经内联了CppClass.cpp中的所有内容(不好,标题内联应该是异常),然后在main.cpp中声明你的类AGAIN,这是C ++中的一个双重声明。在类体中的内联导致每次使用方法时代码重复(这只是听起来很疯狂。)参见 C++ faq有关内联的部分。)



在代码中包含双重声明会产生编译错误。让类代码退出编译,但是给你一个链接器错误,因为现在你只有类似头声明的类声明在main.cpp。链接器没有看到实现你的类方法的代码,这就是为什么错误出现。与Java不同,C ++链接器不会自动搜索它想要使用的对象文件。如果你使用类XYZ,并且不给它XYZ的对象代码,它将会失败。



请看看维基百科的头文件文章头文件包含模式 (链接也位于维基百科文章的底部,并包含更多示例)



简而言之:



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



在NewClass.h文件中,写入:


$ b b

  class NewClass {
public:
NewClass();
int methodA();
int methodB();
}; < - 不要忘记分号

在NewClass.cpp文件中,写入:

  #includeNewClass.h

NewClass :: NewClass(){
// constructor在这里
}

int NewClass :: methodA(){
// methodA到这里
return 0;
}

int NewClass :: methodB(){
// methodB到这里
return 1;
}

在main.cpp中,写入:

  #includeNewClass.h

int main(){
NewClass nc;
//使用nc
执行某项操作}

做一个



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



/ p>

I want to call a few "static" methods of a CPP class defined in a different file but I'm having linking problems. I created a test-case that recreates my problem and the code for it is below.

(I'm completely new to C++, I come from a Java background and I'm a little familiar with 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;
                }
        }
}

When I tried to compile, I get the following error:

$ 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

But if I remove the class declaration in main.cpp and replace it with #include "CppClass.cpp", it works fine. Basically, I want to put these declarations in a separate .h file and use it. Am I missing something?

Thanks for the help.

解决方案

It's obvious you come from a Java background because you haven't yet grasped the concept of header files. In Java the process of defining something is usually in one piece. You declare and define at the same time. In C/C++ it's a two-step process. Declaring something tells the compiler "something exists with this type, but I'll tell you later how it is actually implemented". Defining something is giving the compiler the actual implementation part. Header files are used mostly for declarations, .cpp files for definitions.

Header files are there to describe the "API" of classes, but not their actual code. It is possible to include code in the header, that's called header-inlining. You have inlined everything in CppClass.cpp (not good, header-inlining should be the exception), and then you declare your class in main.cpp AGAIN which is a double declaration in C++. The inlining in the class body leads to code reduplication everytime you use a method (this only sounds insane. See the C++ faq section on inlining for details.)

Including the double declaration in your code gives you a compiler error. Leaving the class code out compiles but gives you a linker error because now you only have the header-like class declaration in main.cpp. The linker sees no code that implements your class methods, that's why the errors appear. Different to Java, the C++ linker will NOT automatically search for object files it wants to use. If you use class XYZ and don't give it object code for XYZ, it will simply fail.

Please have a look at Wikipedia's header file article and Header File Include Patterns (the link is also at the bottom of the Wikipedia article and contains more examples)

In short:

For each class, generate a NewClass.h and NewClass.cpp file.

In the NewClass.h file, write:

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

In the NewClass.cpp file, write:

#include "NewClass.h"

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

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

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

In main.cpp, write:

#include "NewClass.h"

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

To link it all together, do a

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

(just an example with gcc)

这篇关于问题链接“静态” C ++中的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆