SYMPTOMS
You may get compiler error C2535 on a class developed in
Active Template Library (ATL) when compiled in ATL version 3.0. In previous
versions of ATL, a compiler error was not generated for the same class. For
example, if your class looks like the following, you will get the error with
Visual C++ version 6.0/Visual C++ .NET/Visual C++ 2005:
//CCOMTest
class CCOMTest : public CComObjectRootEx<CComMultiThreadModel>
{
public:
// Constructor, Destructor
CCOMTest() {};
~CCOMTest() {};
// Interface Map
BEGIN_COM_MAP(CCOMTest)
END_COM_MAP()
DECLARE_NO_REGISTRY()
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID piid, void **ppv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
private:
LONG mlRef; //Reference count
};
CAUSE
The implementation of END_COM_MAP between Visual C++
version 5.0 and Visual C++ version 6.0 has changed. In Visual C++ 5.0,
END_COM_MAP was defined as the following:
#ifdef _ATL_DEBUG_QI
#define END_COM_MAP() {NULL, 0, 0}}; return &_entries[1];}
#else
#define END_COM_MAP() {NULL, 0, 0}}; return _entries;}
#endif // _ATL_DEBUG_QI
In Visual C++ 6.0, it is defined as follows:
#ifdef _ATL_DEBUG
#define END_COM_MAP() {NULL, 0, 0}}; return &_entries[1];} \
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; \
virtual ULONG STDMETHODCALLTYPE Release( void) = 0; \
STDMETHOD(QueryInterface)(REFIID, void**) = 0;
#else
#define END_COM_MAP() {NULL, 0, 0}}; return _entries;} \
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; \
virtual ULONG STDMETHODCALLTYPE Release( void) = 0; \
STDMETHOD(QueryInterface)(REFIID, void**) = 0;
#endif // _ATL_DEBUG
In Visual C++ .NET, it is defined as follows:
#ifdef _ATL_DEBUG
#define END_COM_MAP() \
__if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
{NULL, 0, 0}}; return &_entries[1];} \
virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
#else
#define END_COM_MAP() \
__if_exists(_GetAttrEntries) {{NULL, (DWORD_PTR)_GetAttrEntries, _ChainAttr }, }\
{NULL, 0, 0}}; return _entries;} \
virtual ULONG STDMETHODCALLTYPE AddRef( void) throw() = 0; \
virtual ULONG STDMETHODCALLTYPE Release( void) throw() = 0; \
STDMETHOD(QueryInterface)(REFIID, void**) throw() = 0;
#endif // _ATL_DEBUG
RESOLUTION
In Visual C++ version 6.0/Visual C++ .NET, you can comment out the IUnknown
methods that were implemented or add something like the following code sample:
#ifdef _ATL_DEBUG
#define END_MY_COM_MAP() {NULL, 0, 0}}; return &_entries[1];}
#else
#define END_MY_COM_MAP() {NULL, 0, 0}}; return _entries;}
#endif // _ATL_DEBUG
// CCOMTest
class CCOMTest: public CComObjectRootEx<CComMultiThreadModel>
{
public:
// Constructor, Destructor
CCOMTest() {};
~CCOMTest() {};
// Interface Map
BEGIN_COM_MAP(CCOMTest)
END_MY_COM_MAP()
DECLARE_NO_REGISTRY()
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID piid, void **ppv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
private:
LONG mlRef; //Reference count
};