You receive a C2335 error message when you compile an ATL project with Visual C++ (241852)



The information in this article applies to:

  • The Microsoft Active Template Library (ATL) 3.0, when used with:
    • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
    • Microsoft Visual C++, 32-bit Professional Edition 6.0
    • Microsoft Visual C++, 32-bit Learning Edition 6.0
    • Microsoft Visual C++ .NET (2002)
    • Microsoft Visual C++ .NET (2003)
    • Microsoft Visual C++ 2005 Express Edition

This article was previously published under Q241852
Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. Microsoft Visual C++ 2005 supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model.

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
};
				

STATUS

This behavior is by design.

Modification Type:MajorLast Reviewed:1/5/2006
Keywords:kberrmsg kbprb KB241852 kbAudDeveloper