C++ - 对最近创建的类的未定义引用!

发布于 2024-07-24 21:56:43 字数 2733 浏览 6 评论 0原文

我刚刚创建了这个新类:

//------------------------------------------------------------------------------
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H
//------------------------------------------------------------------------------
#include <vector>
#include <GL/GLFW.h>
//------------------------------------------------------------------------------
template<class T>
class MultithreadedVector {

    public:

        MultithreadedVector();

        void push_back(T data);

        void erase(typename std::vector<T>::iterator it);

        std::vector<T> get_container();
    private:

        std::vector<T> container_;
        GLFWmutex th_mutex_;


};
//------------------------------------------------------------------------------
#endif // MULTITHREADEDVECTOR_H_INCLUDED
//------------------------------------------------------------------------------

该类的定义:

//------------------------------------------------------------------------------
#include "MultithreadedVector.h"
//------------------------------------------------------------------------------
using namespace std;
//------------------------------------------------------------------------------
template<class T>
MultithreadedVector<T>::MultithreadedVector() {

    th_mutex_ = glfwCreateMutex();
}

template<class T>
void MultithreadedVector<T>::push_back(T data) {

    glfwLockMutex(th_mutex_);
    container_.push_back(data);
    glfwUnlockMutex(th_mutex_);

}

template<class T>
void MultithreadedVector<T>::erase(typename vector<T>::iterator it) {

    glfwLockMutex(th_mutex_);
    container_.erase(it);
    glfwUnlockMutex(th_mutex_);
}

template<class T>
vector<T> MultithreadedVector<T>::get_container() {


    return container_;

}

现在的问题是,当我尝试在代码中将它用作另一个类的静态成员时:

// VehicleManager.h
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

#include "MultithreadedVector.h"
#include "Vehicle.h"
class Foo {

   public:
     // stuffs
   private:
     static MultithreadedVector<Vehicle> vehicles_; 
     ...
}

#endif

然后在里面:VehicleManager.cpp

#include "VehicleManager.h"

MultithreadedVector<Vehicle> VehicleManager::vehicles_;

void VehicleManager::Method() {

  Vehicle vehicle;
  VehicleManager::vehicles_.push_back(vehicle);

}

但它无法编译:(,我每次都会收到此错误消息:

C:\***\VehicleManager.cpp|188|undefined reference to `MultithreadedVector<Vehicle>::push_back(Vehicle)'|

我真的不明白为什么,尤其是我在 VehicleManager.cpp 的全局范围内定义了静态类成员。

PS:我正在使用 Code::Blocks,

谢谢!

I just created this new class :

//------------------------------------------------------------------------------
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H
//------------------------------------------------------------------------------
#include <vector>
#include <GL/GLFW.h>
//------------------------------------------------------------------------------
template<class T>
class MultithreadedVector {

    public:

        MultithreadedVector();

        void push_back(T data);

        void erase(typename std::vector<T>::iterator it);

        std::vector<T> get_container();
    private:

        std::vector<T> container_;
        GLFWmutex th_mutex_;


};
//------------------------------------------------------------------------------
#endif // MULTITHREADEDVECTOR_H_INCLUDED
//------------------------------------------------------------------------------

The definition of the class :

//------------------------------------------------------------------------------
#include "MultithreadedVector.h"
//------------------------------------------------------------------------------
using namespace std;
//------------------------------------------------------------------------------
template<class T>
MultithreadedVector<T>::MultithreadedVector() {

    th_mutex_ = glfwCreateMutex();
}

template<class T>
void MultithreadedVector<T>::push_back(T data) {

    glfwLockMutex(th_mutex_);
    container_.push_back(data);
    glfwUnlockMutex(th_mutex_);

}

template<class T>
void MultithreadedVector<T>::erase(typename vector<T>::iterator it) {

    glfwLockMutex(th_mutex_);
    container_.erase(it);
    glfwUnlockMutex(th_mutex_);
}

template<class T>
vector<T> MultithreadedVector<T>::get_container() {


    return container_;

}

Now the problem is that when i try to use it in my code as a static member of another class :

// VehicleManager.h
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

#include "MultithreadedVector.h"
#include "Vehicle.h"
class Foo {

   public:
     // stuffs
   private:
     static MultithreadedVector<Vehicle> vehicles_; 
     ...
}

#endif

Then inside : VehicleManager.cpp

#include "VehicleManager.h"

MultithreadedVector<Vehicle> VehicleManager::vehicles_;

void VehicleManager::Method() {

  Vehicle vehicle;
  VehicleManager::vehicles_.push_back(vehicle);

}

But it doesn't compile :(, i get this error msg everytime :

C:\***\VehicleManager.cpp|188|undefined reference to `MultithreadedVector<Vehicle>::push_back(Vehicle)'|

I really don't understand why, especially that i have defined the static class member at the global scope of VehicleManager.cpp.

PS: I'm using Code::Blocks.

Thanks !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

¢好甜 2024-07-31 21:56:43

这就是盲目地将类模板实现移至 cpp 文件时会发生的情况。

为了实现这一点,您必须确切地知道您将实例化类模板的 T 类型并在 cpp 文件中指定它们。

在这种情况下,请将其放入 cpp 文件中:

template class MultithreadedVector<Vehicle>;

请注意,cpp 文件必须了解 Vehicle

That's what will happen when blindly moving a class template implementation to a cpp file.

To make that work, you must know exactly for what types of T you will instantiate the class template and specify them in the cpp file.

In this case, put this in the cpp file:

template class MultithreadedVector<Vehicle>;

Note that the cpp file must know about Vehicle then.

囍孤女 2024-07-31 21:56:43

大多数 C++ 编译器不允许将模板声明和模板定义分开。 您需要将模板类的完整定义放在单个 .h 文件中,而不是将它们拆分为 .h 和 .cpp 文件。

Most C++ compilers to not allow you to separate template declarations and template definitiions. You need to put the complete definition of your template classes in a single .h file, not split them into .h and .cpp files.

書生途 2024-07-31 21:56:43

当编译器看到模板的使用时,模板实现的完整代码必须对编译器可见,以便编译器可以实例化模板并将其编译成稍后可以链接的目标代码。

在声明模板的同一头文件中定义模板代码。

The complete code of template implementation must be visible to the compiler at the point it sees the use of template so it can instantiate the template and compile it into object code that can be later linked.

Define the template code in the same header file as the template is declared.

爱她像谁 2024-07-31 21:56:43

我认为有两种情况可以使用模板

  1. 为任意一组符合类型提供通用代码
  2. 为一组固定类型提供通用代码

对于第二种情况,您不需要将模板放入标头中:因为您知道事先准确地确定您的模板使用的类型。 您可以很好地定义类模板的成员函数,或在单独的翻译单元中定义函数模板,而不会出现链接器错误。 有些人总是教导别人这是不可能的,以此混淆视听。

但我认为这取决于这两种情况是否要将声明和定义分离到不同的翻译单元中。

  • 如果您想使用情况 1,则始终希望在标头中包含定义(无论是包含在特殊命名文件中,例如 .ipp.tcc 或任何)。 即使在这种情况下,我只知道一个支持将定义与声明分离的 C++ 前端,即 EDG(爱迪生设计组)前端,由 intel 和 comeau 编译器使用,它实现了导出。 该关键字被某些人视为错误功能,并且大多数编译器都没有实现它。

  • 如果您想使用情况 2,那么将定义放入标头中是没有好处的,因为没有理由这样做:您只需显式实例化固定类型集所需的函数和类。 在第二种情况下,您可以使用模板来减轻维护可能冗余代码的负担,并且可以选择在某些情况下为某些类型引入特殊行为。

您的场景显然是第一种情况,因此您必须将定义放入标头中。

I think there are two cases how one can use templates

  1. Providing generic code for an arbitrary set of conforming types
  2. Providing generic code for a fixed set of types

For the second one, you don't need to put templates into the header: Since you know beforehand, precisely, with what types your template is used. You can very well define a class template's member function, or a function template in a separate translation unit, without linker errors. Some people keep teaching others that this is not possible, and confuse the matter by this.

But i think it depends on these two cases whether you want to separate declaration and definition into different translation units or not.

  • If you want to use case 1, you always want to have the definition in the header (whether included by special named files, like .ipp, .tcc or whatever). I only know of one C++ frontend that supports separating definition from declarations even in this case, which is the EDG (edison design group) frontend, used by the intel and comeau compilers, that implement export. That keyword is seen as a misfeature by some, and most compilers don't implement it.

  • And if you want to use case 2, it's no good to put the definitions into the header, because there would be no reason to do so: You will just explicitly instantiate the needed functions and classes for the fixed set of types. In this second scenario, you use the template to save yourself from the burden to maintain possibly redundant code, and have the option open to introduce special behavior for some types in some cases.

Your scenario is clearly a case 1 situation, and so you will have to put your definitions into the header.

不知在何时 2024-07-31 21:56:43

您似乎在 VehicleManager.h 中存在复制和粘贴错误:

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

这禁止包含定义了 Foo 类的头文件。

You seem to have a copy&paste error in VehicleManager.h:

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

This prohibits the inclusion of the header file, where class Foo is defined.

同尘 2024-07-31 21:56:43

大多数情况下,您无法在 cpp 文件中编写模板实现。 将模板实现移至头文件,以便编译器可以正确实例化它。

You cannot write the template implementation in the cpp file in most of the cases. Move the template implementation to the header file so that compiler can instantiate it properly.

梦里°也失望 2024-07-31 21:56:43

除了其他答案之外:

您还必须保护 get_container() 。 此方法基本上复制 container_ 元素,因此必须受到保护。

template<class T>
vector<T> MultithreadedVector<T>::get_container() 
{
    return container_;
}

Apart from the other answers:

You have to guard get_container() as well. This method basically copies the container_ elements and hence must be guarded.

template<class T>
vector<T> MultithreadedVector<T>::get_container() 
{
    return container_;
}
秋凉 2024-07-31 21:56:43

模板在某种程度上是一种高级的、专门的宏。 您实际上无法像您试图做的那样单独编译模板定义。

对于大多数人来说,这意味着他们甚至懒得将模板定义与声明分开。 我有一位同事更进一步,并且拒绝分开< em>非模板定义和声明也是如此。

如果您想从声明中放入模板的定义,您确实有几个选择。

第一个选项是使用 C++“export”关键字。 这个看似简单的解决方案的问题在于 没有人支持它。 对于编译器编写者来说,实现起来太困难了。

第二种选择是使用第三种类型的文件,通常为声明标记为“.ipp”。 这里的技巧是,它仍然是一个必须是“#included”的文件,但作为一个单独的文件,您只需将其包含在“.cpp”文件中。 我发现我的链接器不喜欢在单个程序的多个“.cpp”文件中#include“.ipp”,因此您必须选择一个作为包含器。

A template in a way is kind of an advanced, specialized kind of macro. You cannot actually compile a template defintion separately like it looks like you are trying to do.

For most people, this means they don't even bother to separate teplate definitions from their declarations. I have one co-worker who takes this a step further, and refuses to separate non-template definitions and declarations too.

If you want to put the definition of a template from the declaration, you do have a couple of options though.

The first option is to use the C++ "export" keyword. The problem with this seemingly simple solution is that nobody supports it. It is too tough for compiler writers to implement.

The second option is to use a third type of file, often tagged ".ipp", for the declarations. The trick here is that it is still a file that must be "#included", but being a separate file, you only have to include it in ".cpp" files. I've found my linker doesn't like it if I #include a ".ipp" in more than one ".cpp" file in a single program, so you do have to pick one be the includer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文