C++使用接口类、模板和对象工厂构建API
我想构建一个API,为功能头文件提供一个类接口,并出于所有标准的原因隐藏实现。我计划使用对象工厂返回符合接口的派生新对象的对象指针 我的核心API类根据内置数字类型的std::vectors而有所不同—Schar、uchar、short、ushort、int、uint、float和double。因此,模板似乎是一种自然的匹配。我将为API的用户提供一个接口类模板,并在将隐藏的实现类模板中从中派生 由于我的用户可见类模板是一个接口类,我想将所有方法都声明为纯虚拟的,但我知道在DLL、共享对象等中给定所需的模板实例化/导出时,这样做可能会有问题。因此,我将只定义它们为虚拟的,并在基本接口类中为它们提供空的方法体。在此过程中,我需要创建一个模板静态工厂方法或模板函数,它将创建派生类的对象,并将指向它们的指针返回给调用方 问题是我不能将静态对象工厂方法的实现放在接口头文件中,因为它必须创建要隐藏的派生类的对象。所以我想把这些静态对象工厂放在实现头文件或源文件中 这是一个概念性的实现头C++使用接口类、模板和对象工厂构建API,c++,visual-studio,templates,factory,factory-pattern,C++,Visual Studio,Templates,Factory,Factory Pattern,我想构建一个API,为功能头文件提供一个类接口,并出于所有标准的原因隐藏实现。我计划使用对象工厂返回符合接口的派生新对象的对象指针 我的核心API类根据内置数字类型的std::vectors而有所不同—Schar、uchar、short、ushort、int、uint、float和double。因此,模板似乎是一种自然的匹配。我将为API的用户提供一个接口类模板,并在将隐藏的实现类模板中从中派生 由于我的用户可见类模板是一个接口类,我想将所有方法都声明为纯虚拟的,但我知道在DLL、共享对象等中给
#ifndef INTERFACE_H
#define INTERFACE_H
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
// This interface class is exported from the dll.
template < typename T >
class DLL_API InterfaceClass {
public:
static InterfaceClass* factoryMethod( );
virtual ~InterfaceClass ( ) { }
virtual void someMethod( T aParam ){ };
protected:
InterfaceClass ( ) { }
private:
InterfaceClass ( const InterfaceClass & );
InterfaceClass& operator=( const InterfaceClass & );
};
#endif
下面是一个概念派生的实现类
#ifndef IMPLEMENTATION_H
#define IMPLEMENTATION_H
#include <vector>
#include "interface.h"
template < typename T >
class DerivedClass : public InterfaceClass< T > {
public:
DerivedClass( const T& aDataVector ) : InterfaceClass< T >( ) { /*...*/ }
virtual ~DerivedClass( ) { /*...*/ }
virtual void someMethod( T aParam ) { /*...*/ }
private:
std::vector< T > _dataVector;
})
注意:实际上,我将使用TR1::shared_ptr而不是原始指针
我的问题是:
1在哪里定义静态factoryMethod implementation.h或implementation.cpp
2这个方法的实现是什么样子的
3是否有任何其他问题需要注意,以便我或我的API用户不会出现链接时间或运行时错误
提前谢谢 您将遇到以下问题: 1类DLL不能公开模板,因为它们是在编译时填充的。也就是说,如果您有DerivedClass,编译器实际上会在需要定义对象的任何地方填充int。如果试图通过DLL公开它,则尝试与您的对象链接的应用程序的客户端代码可能会尝试创建DerivedClass对象,您将收到链接器错误,因为它不存在
< 2 >虽然C++技术上允许模板类被分割为实现和头文件,但是编译器没有支持该特性,因为尝试实现它是一种巨大的痛苦。这包括微软的C++编译器。有两种方法可以解决这个问题:在头文件中内联编写类,这是大多数STL实现所做的,或者在头文件的底部包含实现文件,这基本上做了相同的事情,但不是真正的标准做法。我让它在Visual studio 2008下工作 详情如下: 接口.h
#ifndef INTERFACE_H
#define INTERFACE_H
#if defined( WIN32 ) || defined ( WIN64 )
#ifdef DLL_EXPORTS
#define DECLSPECIFIER __declspec( dllexport )
#define EXPIMP_TEMPLATE
#else // DLL_EXPORTS
#define DECLSPECIFIER __declspec( dllimport )
#define EXPIMP_TEMPLATE extern
#endif // DLL_EXPORTS
#else // defined( WIN32 ) || defined ( WIN64 )
#define DECLSPECIFIER
#define EXPIMP_TEMPLATE
#endif // defined( WIN32 ) || defined ( WIN64 )
// This class is exported from the dll.
template < typename T >
class DECLSPECIFIER InterfaceClass {
public:
static InterfaceClass* factoryMethod( );
virtual ~InterfaceClass( ) { }
virtual void someMethod( ) { }
protected:
InterfaceClass( ) { }
private:
InterfaceClass( const InterfaceClass& );
InterfaceClass& operator=( const InterfaceClass& );
};
#if defined( WIN32 ) || defined ( WIN64 )
#pragma warning( push )
#pragma warning( disable: 4231 ) // "nonstandard extension used : 'extern'
// ok per [link text][1]
#endif
#include <vector>
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< char > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< unsigned char > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< short > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< unsigned short > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< int > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< unsigned int > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< float > >;
EXPIMP_TEMPLATE template class DECLSPECIFIER InterfaceClass < std::vector< double > >;
#if defined( WIN32 ) || defined ( WIN64 )
#pragma warning( pop )
#endif
#endif
导出的.h
#ifndef DERIVED_H
#define DERIVED_H
#include <iostream>
#include "interface.h"
template < typename T >
class DerivedClass : public InterfaceClass< T > {
public:
DerivedClass( ) {
std::cout << "constructing derived class" << std::endl;
}
virtual ~DerivedClass( ) {
std::cout << "destructing derived class" << std::endl;
}
virtual void someMethod( ) {
std::cout << "hello" << std::endl;
}
private:
T _data;
};
#endif
interface.cpp
#include "interface.h"
#include "derived.h"
template < typename T >
DECLSPECIFIER
InterfaceClass<T>* InterfaceClass< T >::factoryMethod( ) {
return new DerivedClass< T >( );
}
client.cpp
#include <exception>
#include "interface.h"
typedef InterfaceClass < std::vector< int > > IntVectorType;
int main(int argc, char* argv[])
{
IntVectorType* ptrTest = NULL;
try {
ptrTest = IntVectorType::factoryMethod( );
}
catch ( std::bad_alloc& ) {
return 1;
}
ptrTest->someMethod( );
delete ptrTest;
return 0;
}
这可能是非标准的,但它非常有用。
一个编译器,CuMuC++,支持模板类的分割。该选项几乎肯定会从标准中删除,Comeau支持这样做。我在VisualStudio2008下使用了它