Visual C++: Warnung C4251

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

 

CO2

ehemals "SirMO"

Betreff: Visual C++: Warnung C4251

BeitragFr, Sep 16, 2016 23:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Einen wunderschönen guten Abend.

Ich habe wieder Sehnsucht nach C++ und habe mich auch gleich mal an ein Projekt gesetzt. Idee: SDL lernen - soweit, so gut. Meine Solution ist nun in drei Teile geteilt:
Arrow SDL2.DLL, welche den unveränderten Quellcode von SQL enthält (https://www.libsdl.org/download-2.0.php).
Arrow GameBase.DLL, welche Klassen von mir enthält.
Arrow Main.EXE, welche die main()-Funktion enthält.

Das Problem liegt in der GameBase.DLL: Hier habe ich ein Template einer Pointerliste, basierend auf dem std::vector. Die Definition sieht wie folgt aus Code: [AUSKLAPPEN]
template <class T>
class CPtrList
{
private:
   std::vector<T *> m_lData;
   bool             m_bAutoDelete;

public:
   CPtrList(bool bAutoDelete = false)
      : m_lData(), m_bAutoDelete(bAutoDelete)
   {
   }

   ~CPtrList()
   {
      if (m_bAutoDelete)
         DeleteAll();
   }

public:
   size_t GetCount()
   {
      return m_lData.size();
   }

   bool IsEmpty()
   {
      return m_lData.empty();
   }

   void Add(T *pNewElem, bool bCheckNull = true)
   {
      if (!bCheckNull || (bCheckNull && pNewElem))
         m_lData.push_back(pNewElem);
   }

   T *Remove(size_t iPosition)
   {
      if (iPosition < GetCount())
      {
         m_lData.erase(m_lData.begin() + iPosition);
         return GetAt(iPosition);
      }
      else
         return nullptr;
   }

   void DeleteAll()
   {
      for (size_t pos = 0; pos < GetCount(); pos++)
      {
         T* pTemp = GetAt(pos);
         if (pTemp)
            SDEL(pTemp);
      }

      m_lData.clear();
   }

   T *GetAt(size_t iPosition)
   {
      if (iPosition < GetCount())
         return m_lData.at(iPosition);
      else
         return nullptr;
   }
};


Nun möchte ich mir ein Pseudo-Dateisystem aufsetzen und ähnlich wie in BlitzMax dort Dateien als Stream aus einer zusammengefassten Datei laden können. Dies habe ich mir so gedacht, dass ich praktisch den real existierenden Dateinamen des Paketes und ein Alias, wie es innerhalb des Programms heißen soll, angeben will. Ich habe bereits den Rahmen der Klasse erstellt, dieser sieht so aus Code: [AUSKLAPPEN]
class BASEAPI CFileSystem final
{
private:
   class CMount
   {
   private:
      CString m_sFile;
      CString m_sAlias;

   public:
      CMount(CString sFile, CString sAlias);

   //public:
   //    Stream *GetFile(CString sFilename);   
   };

private:
   CPtrList<CMount> m_arMounts;

public:
   CFileSystem();

public:
   void Mount(const CString &sFile, const CString &sAlias);

   // Stream *GetFile(CString sFile, CString sMount = "");
};


Nun der problematische Teil: Beim kompilieren bekomme ich die Warnung C4251, Zitat: "warning C4251: "CFileSystem::m_arMounts": class "CPtrList<CFileSystem::CMount>" erfordert eine DLL-Schnittstelle, die von Clients von class "CFileSystem" verwendet wird". Ich las im Internet (http://www.unknownroad.com/rtf...C4251.html), dass dies daran liegt, dass die spezielle Definition des CPtrList-Templates auf CMount nicht exportiert wird und habe versucht, dies folgendermaßen zu umgehen Code: [AUSKLAPPEN]
(...)
   //public:
   //    Stream *GetFile(CString sFilename);   
   };

private:
   template class BASEAPI CPtrList<CMount>;
   CPtrList<CMount> m_arMounts;

public:
   CFileSystem();
(...)
, dies führt jedoch zu einem Fehler: "error C2252: Eine explizite Instanziierung einer Vorlage kann nur im Namespacebereich erfolgen.".

Meine Frage: Wie umgeht man diese Warnung, ohne sie zu disablen?
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

Thunder

BeitragSa, Sep 17, 2016 12:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Es ist das gleiche wie immer: du weigerst dich, deine Templates in Header-Dateien zu stecken und sie einfach zu includen.

Aber bitte, ich denke das ist der Microsoft-Artikel, den du suchst: https://support.microsoft.com/en-us/kb/168958
Zitat:
To Export a Class Containing a Data Member that Is an STL Object

- In both the DLL and the .exe file, link with the same DLL version of the C run time. Either link both with Msvcrt.lib (release build) or link both with Msvcrtd.lib (debug build).

- In the DLL, provide the __declspec specifier in the template instantiation declaration to export the STL class instantiation from the DLL.

NOTE: You cannot skip step 2. You must export the instantiation of the STL class that you use to create the data member.
- In the DLL, provide the __declspec specifier in the declaration of the class to export the class from the DLL.

- In the .exe file, provide the __declspec specifier in the declaration of the class to import the class from the DLL.

If the class you are exporting has one or more base classes, then you must export the base classes as well. If the class you are exporting contains data members that are of class type, then you must export the classes of the data members as well.
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group