سؤال

لقد قمت للتو بإنشاء هذه الفئة الجديدة:

//------------------------------------------------------------------------------
#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.

ملاحظة:أنا أستخدم Code::Blocks.

شكرًا !

هل كانت مفيدة؟

المحلول

وهذا ما سيحدث عندما عمياء تحريك تنفيذ قالب فئة إلى ملف حزب الشعب الكمبودي.

لجعل هذا العمل، يجب أن تعرف بالضبط ما أنواع T سوف مثيل قالب فئة وتحديدها في ملف حزب الشعب الكمبودي.

في هذه الحالة، وضعت هذا في ملف حزب الشعب الكمبودي:

template class MultithreadedVector<Vehicle>;

لاحظ أن ملف حزب الشعب الكمبودي يجب أن يعرف عن Vehicle ذلك الحين.

نصائح أخرى

ومعظم المجمعين C ++ للا يسمح لك لفصل الإعلانات قالب وdefinitiions القالب. تحتاج إلى وضع تعريف كامل للفئات القالب في ملف .h واحد، وليس تقسيمها إلى .H و.CPP الملفات.

ويجب أن يكون رمز كاملة من تنفيذ قالب مرئية للمترجم عند نقطة ما تراه استخدام قالب لذلك يمكن إنشاء مثيل القالب وترجمة ذلك إلى رمز الكائن التي يمكن ربطها لاحقا.

وتحديد رمز القالب في نفس ملف الرأس كما أعلن القالب.

أعتقد أن هناك حالتين يمكن من خلالهما استخدام القوالب

  1. توفير كود عام لمجموعة عشوائية من الأنواع المطابقة
  2. توفير كود عام لمجموعة ثابتة من الأنواع

بالنسبة للخيار الثاني، لا تحتاج إلى وضع قوالب في الرأس:نظرًا لأنك تعرف مسبقًا، بدقة، الأنواع التي سيتم استخدام القالب الخاص بك فيها.يمكنك تحديد وظيفة عضو قالب الفصل بشكل جيد، أو قالب الوظيفة في وحدة ترجمة منفصلة، ​​دون أخطاء الرابط.ويظل بعض الناس يعلمون الآخرين أن هذا غير ممكن، ويخلطون الأمر بهذا.

لكنني أعتقد أن الأمر يعتمد على هاتين الحالتين سواء كنت تريد فصل الإعلان والتعريف إلى وحدات ترجمة مختلفة أم لا.

  • إذا كنت تريد استخدام الحالة 1، فأنت تريد دائمًا أن يكون التعريف في الرأس (سواء تم تضمينه بواسطة ملفات مسماة خاصة، مثل .ipp, .tcc أو أيا كان).أعرف فقط واجهة أمامية واحدة فقط لـ C++ تدعم فصل التعريف عن الإعلانات حتى في هذه الحالة، وهي الواجهة الأمامية EDG (مجموعة تصميم إديسون)، التي يستخدمها مترجمو intel وcomeau، والتي تنفذ export.ينظر البعض إلى هذه الكلمة الرئيسية على أنها ميزة غير صحيحة، ولا ينفذها معظم المترجمين.

  • وإذا كنت تريد استخدام الحالة 2، فليس من الجيد وضع التعريفات في الرأس، لأنه لن يكون هناك سبب للقيام بذلك:ستقوم فقط بإنشاء مثيل للوظائف والفئات المطلوبة بشكل صريح لمجموعة الأنواع الثابتة.في هذا السيناريو الثاني، يمكنك استخدام القالب لإنقاذ نفسك من عبء الحفاظ على التعليمات البرمجية التي قد تكون زائدة عن الحاجة، ويكون لديك خيار مفتوح لتقديم سلوك خاص لبعض الأنواع في بعض الحالات.

من الواضح أن السيناريو الخاص بك هو حالة الحالة الأولى، ولذلك سيتعين عليك وضع تعريفاتك في الرأس.

ويبدو أن لديها خطأ نسخ و لصق في VehicleManager.h:

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

وهذا يمنع إدراج ملف الرأس، حيث يتم تعريف الطبقة فو.

ولا يمكنك الكتابة تنفيذ القالب في ملف حزب الشعب الكمبودي في معظم الحالات. نقل تنفيذ القالب إلى ملف الرأس بحيث مترجم يمكن إنشاء مثيل بشكل صحيح.

وبصرف النظر عن إجابات أخرى:

لديك لحراسة get_container() كذلك. هذه الطريقة أساسا نسخ العناصر container_، وبالتالي يجب أن يكون حذرا.

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

يعد القالب بطريقة ما نوعًا متقدمًا ومتخصصًا من وحدات الماكرو.لا يمكنك في الواقع تجميع تعريف القالب بشكل منفصل كما يبدو أنك تحاول القيام به.

بالنسبة لمعظم الناس، هذا يعني أنهم لا يكلفون أنفسهم عناء فصل تعريفات اللوحة عن إعلاناتهم.لدي زميل في العمل يأخذ هذه خطوة إلى الأمام, ، ويرفض الانفصال غير القالب التعريفات والإعلانات أيضا.

إذا كنت تريد وضع تعريف لقالب من الإعلان، فلديك خياران بالرغم من ذلك.

الخيار الأول هو استخدام الكلمة الأساسية "تصدير" C++.المشكلة في هذا الحل الذي يبدو بسيطًا هو أنه لا أحد يدعم ذلك.إنه أمر صعب للغاية بالنسبة للكتاب المترجمين للتنفيذ.

الخيار الثاني هو استخدام أ النوع الثالث من الملفات, ، وغالبًا ما يتم وضع علامة ".ipp" عليها بالنسبة للإعلانات.الحيلة هنا هي أنه لا يزال ملفًا يجب أن يكون "#included"، ولكن كونه ملفًا منفصلاً، ما عليك سوى تضمينه في ملفات ".cpp".لقد وجدت أن الرابط الخاص بي لا يعجبه إذا قمت بتضمين ملف ".ipp" في أكثر من ملف ".cpp" في برنامج واحد، لذلك يتعين عليك اختيار ملف ليكون المضمن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top