导出类成员里含有stl对象
How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object
Summary
- Export an instantiation of a Standard Template Library (STL) class.
- Export a class that contains a data member that is an STL object.
Note that you may not export a generalized template. The template must be instantiated; that is, all of the template parameters must be supplied and must be completely defined types at the point of instantiation. For instance "stack<int>;" instantiates the STL stack class. The instantiation forces all members of class stack<int> to be generated.
Also note that some STL containers (map, set, queue, list, deque) cannot be exported. Please refer to the More Information section to follow for a detailed explanation.
More Information
To Export an STL Class
- 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.
- In the .exe file, provide the extern and __declspec specifiers in the template instantiation declaration to import the class from the DLL. This results in a warning C4231 "nonstandard extension used : 'extern' before template explicit instantiation." You can ignore this warning.
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.
NOTE: Some STL classes use other STL classes. These other classes must also be exported. The classes that must be exported are listed in compiler warnings if you compile with a warning level lower than 1; that is, /W2, /W3, or /W4. Warning level 4 generates a lot of warning messages for STL headers and is not currently recommended for that reason.
Some STL classes contain nested classes. These classes can not be exported. For instance, deque contains a nested class deque::iterator. If you export deque, you will get a warning that you must export deque::iterator. If you export deque::iterator, you get a warning that you must export deque. This is caused by a designed limitation that once a template class is instantiated, it can not be re-instantiated and exported. The only STL container that can currently be exported is vector. The other containers (that is, map, set, queue, list, deque) all contain nested classes and cannot be exported.
When you export an STL container parameterized with a user-defined type (UDT), you must define the operators < and == for your UDT. For example, if you export vector<MyClass>, you must define MyClass::operator < and MyClass operator ==. This is because all STL container classes have member comparison operators that require the existence of the operators < and == for the contained type. Normally, these are not instantiated because they are not used. When you instantiate an instance of a template class, all member functions are generated. Because the STL container classes have member functions that use the operators < and == for the contained type, you must implement them. If comparing objects of your UDT does not make sense, you can define the comparison operators to simply return "true."
When the symbol _DLL is defined during compiling (this symbol is implicitly defined when compiling with /MD or /MDd to link with the DLL version of the C Runtime), the following STL classes, and various global operators and functions that operate on these classes, are already exported by the C Runtime DLL. Therefore, you cannot export them from your DLL. This should not cause a problem for the executable program that imports your class as long as it also uses the DLL version of the C run time:
Header STL template class
------------------------------
<IOSFWD> basic_ios
<IOSFWD> <IOSFWD>
<IOSFWD> basic_istream
<IOSFWD> basic_string (also typedef'd as string and wstring)
<IOSFWD> complex
<LOCALE> messages
<XLOCALE> codecvt
<XLOCALE> ctype
<XLOCMON> moneypunct
<XLOCMON> money_get
<XLOCMON> money_put
<XLOCNUM> numpunct
<XLOCTIME> time_get
<XLOCTIME> time_put
<XSTRING> basic_string (also typedef'd as string and wstring)
For specific details on which template parameters are used and which global functions and operators are declared, please see the relevant header file.
Sample Code
// -------------------------------------------
// MYHEADER.H
//disable warnings on 255 char debug symbols
#pragma warning (disable : 4786)
//disable warnings on extern before template instantiation
#pragma warning (disable : 4231)
#include <vector>
// Provide the storage class specifier (extern for an .exe file, null
// for DLL) and the __declspec specifier (dllimport for .an .exe file,
// dllexport for DLL).
// You must define EXP_STL when compiling the DLL.
// You can now use this header file in both the .exe file and DLL - a
// much safer means of using common declarations than two different
// header files.
#ifdef EXP_STL
# define DECLSPECIFIER __declspec(dllexport)
# define EXPIMP_TEMPLATE
#else
# define DECLSPECIFIER __declspec(dllimport)
# define EXPIMP_TEMPLATE extern
#endif
// Instantiate classes vector<int> and vector<char>
// This does not create an object. It only forces the generation of all
// of the members of classes vector<int> and vector<char>. It exports
// them from the DLL and imports them into the .exe file.
EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<int>;
EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<char>;
// Declare/Define a class that contains both a static and non-static
// data member of an STL object.
// Note that the two template instantiations above are required for
// the data members to be accessible. If the instantiations above are
// omitted, you may experience an access violation.
// Note that since you are exporting a vector of MyClass, you must
// provide implementations for the operator < and the operator ==.
class DECLSPECIFIER MyClass
{
public:
std::vector<int> VectorOfInts;
static std::vector<char> StaticVectorOfChars;
public:
bool operator < (const MyClass > c) const
{
return VectorOfInts < c. VectorOfInts;
}
bool operator == (const MyClass > c) const
{
return VectorOfInts == c. VectorOfInts;
}
};
// Instantiate the class vector<MyClass>
// This does not create an object. It only forces the generation of
// all of the members of the class vector<MyClass>. It exports them
// from the DLL and imports them into the .exe file.
EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<MyClass>;
// -------------------------------------------
// Compile options needed: /GX /LDd /MDd /D"EXP_STL"
// or: /GX /LD /MD /D"EXP_STL"
// DLL.CPP
#include "MyHeader.h"
std::vector<char> MyClass::StaticVectorOfChars;
// -------------------------------------------
// Compile options needed: /GX /MDd
// or: /GX /MD
// EXE.CPP
#include <iostream>
#include "MyHeader.h"
int main ()
{
MyClass x;
for (int i=0; i<5; i++) x.VectorOfInts.push_back(i);
for (char j=0; j<5; j++) x.StaticVectorOfChars.push_back('a' + j);
std::vector<int>::iterator vii = x.VectorOfInts.begin();
while (vii != x.VectorOfInts.end())
{
std::cout << *vii;
std::cout << " displayed from x.VectorOfInts" << std::endl;
vii++;
}
std::vector<char>::iterator vci = x.StaticVectorOfChars.begin();
while (vci != x.StaticVectorOfChars.end())
{
std::cout << *vci;
std::cout << " displayed from MyClass::StaticVectorOfChars";
std::cout << std::endl;
vci++;
}
std::vector<MyClass> vy;
for (i=0; i=5; i++) vy.push_back(MyClass());
return 1;
}
References
__declspec
stack
/MD, /ML, /MT, /LD (Use Run-Time Library)
Properties
Article ID: 168958 - Last Review: Sep 6, 2005 - Revision: 1
导出类成员里含有stl对象的更多相关文章
- static类成员(变量和函数)
0. 使用背景 对于特定类类型的全体对象而言,访问一个全局对象有时是必要的.也许,在程序的任意点需要统计已创建的特定类类型对象的数量:或者,全局对象可能是指向类的错误处理例程的一个指针:或者,它是指向 ...
- 实战MEF(3):只导出类的成员
通过前面两篇文章的介绍,相信各位会明白MEF中有不少实用价值.上一文中我们也讨论了导入与导出,对于导出导入,今天我们再深入一点点,嗯,只是深入一点点而已,不会很难的,请大家务必放心,如果大家觉得看文章 ...
- python的类和对象——类成员番外篇
学完了面向对象的三大特性,已经get了所有屌丝技能的我们也当一回文艺小青年,来看看类的成员和成员修饰符. 今天‘三’这个数字好亲和~~~类成员可以分为三类:字段.方法和属性 一.字段 首先我们来看看字 ...
- Python_day8_面向对象(多态、成员修饰符、类中特殊方法、对象边缘知识)、异常处理之篇
一.面向对象之多态 1.多态:简而言子就是多种形态或多种类型 python中不支持多态也用不到多态,多态的概念是应用与java/C#中指定传参的数据类型, java多态传参:必须是传参数的数据类型或传 ...
- python-面向对象(四)——类成员的访问方式汇总
类成员的访问方式 #!/usr/bin/env python # _*_coding:utf-8 _*_ class pepole(object): '''This is __doc__ inform ...
- MEF只导出类的成员
MEF只导出类的成员 通过前面两篇文章的介绍,相信各位会明白MEF中有不少实用价值.上一文中我们也讨论了导入与导出,对于导出导入,今天我们再深入一点点,嗯,只是深入一点点而已,不会很难的,请大家务必放 ...
- 类1(this指针/const成员函数/类作用域/外部成员函数/返回this对象的函数)
假设我们要设计一个包含以下操作的 Sales_data 类: 1.一个 isbn 成员函数,用于返回对象的 book_no 成员变量 2.一个 combine 成员函数,用于将一个 Sales_dat ...
- Objective-C类成员变量深度剖析--oc对象内存模型
目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objec ...
- C++类成员变量多用指针不用对象
如A类的成员变量含有B类的对象,那么每个A类对象产生或拷贝都要产生一次B类对象的构造或者拷贝,对象占的空间比较大,对象拷贝比较消耗内存. 如果换成B类的指针,A类对象拷贝,也只会产生4个字节或者8个字 ...
随机推荐
- 阿里云centos6.5实践编译安装LNMP架构web环境
LNMP 代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构. 本次测试需求: **实践centos6.5编译安装 LNMP生产环境 架构 web生产环境 使用 ngx_pa ...
- 在懒加载的Ionic工程中使用 ionic2-auto-complete 组件:Can't bind to 'dataProvider' since it isn't a known property of 'ion-auto-complete'
问题描述: 在基于懒加载的Ionic工程中,使用ionic2-auto-complete组件(GitHub地址:https://github.com/kadoshms/ionic2-autocompl ...
- JS原型与原型链终极讲解
function Person () { this.name = 'John'; } var person = new Person(); Person.prototype.say = functio ...
- tcpcopy简介
本文内容是整理自 王斌的博客(http://blog.csdn.net/wangbin579)和郑钧的博客(http://www.cnblogs.com/zhengyun_ustc),以便让自己可以有 ...
- 对工厂方法模式的一些思考(java语法表示)
同为创造型设计模式的简单工厂模式可以理解为对new关键字的代替. 本着重复三次即重构的原则,如果一个对象在不同的地方被new了两次以上,那就可以考虑使用它.那我们为什么要用简单工厂模式代替new呢?就 ...
- 一个简单的DLL生成和测试
DLL文件内容: SKLDll.h #ifndef _SKLDLL_H_#define _SKLDLL_H_ #ifndef DLL_API #define DLL_API extern " ...
- 51Nod1053 最大M子段和V2 二分+DP
传送门 直接DP的话最多也只能做到\(O(nm)\),对于\(5\times 10^4\)的数据范围实在无能为力 夹克老爷提供的做法是贪心,思想大概是在调整的同时,合理构造每个选择对应的新状态,使得新 ...
- jQuery基础(动画篇 animate,显示隐藏,淡入淡出,下拉切换)
1.jQuery中隐藏元素的hide方法 让页面上的元素不可见,一般可以通过设置css的display为none属性.但是通过css直接修改是静态的布局,如果在代码执行的时候,一般是通过js控制元 ...
- 浏览器根对象window之caches
在控制台输入window. caches可输出一个叫做CacheStorage的对象,它用来存储 Response 对象的.也就是说用来对 HTTP ,响应做缓存的.虽然 localStorage 也 ...
- react 中使用定时器 Timers(定时器)
setTimeout,clearTmeout setInterval,clearInterval 在 class 中 class TimersDemo extends Component { cons ...