如题目所示,ATL的接口对象可以使用CoCreateInstance或者CreateInstance函数创建对象实例。
ATL的类对象应该如何构造呢?多谢各位达人指点!!

解决方案 »

  1.   

    用IDL文件生成xxx_H.h和xxx_.c文件,和使用一般的C++文件一样使用。
      

  2.   

    楼上兄弟,我还是有些不明白。
    比如说我现在有个ATL类CFun,
    接口是IFun。
    如果我创建接口对象,我可以使用如下方法:
    ::CoCreateInstance(......)
    创建接口对象。
    我现在在CFun中定义了几个public类型的成员函数。
    我想通过类对象访问这些成员函数。
    CFun* pFun = new CFun;
    这样写编译就出错。
    请问如何按照你说的方法创建CFun的类对象?
    谢谢!!
      

  3.   

    代码就是这一句,其中CClientRS是ATL类,接口为IClientRS。
    CClientRS* pClientRS = new CClientRS;下面是编译后的错误信息。
    --------------------Configuration: RemoteAccess - Win32 Debug--------------------
    Compiling...
    ClientObj.cpp
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : error C2259: 'CClientRS' : cannot instantiate abstract class due to following members:
            d:\sourcecodes\remoteaccess\clientrs.h(12) : see declaration of 'CClientRS'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'long __stdcall CClientRS::QueryInterface(const struct _GUID &,void ** )' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'QueryInterface'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'unsigned long __stdcall CClientRS::AddRef(void)' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'AddRef'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'unsigned long __stdcall CClientRS::Release(void)' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'Release'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : error C2259: 'CClientRS' : cannot instantiate abstract class due to following members:
            d:\sourcecodes\remoteaccess\clientrs.h(12) : see declaration of 'CClientRS'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'long __stdcall CClientRS::QueryInterface(const struct _GUID &,void ** )' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'QueryInterface'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'unsigned long __stdcall CClientRS::AddRef(void)' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'AddRef'
    D:\SourceCodes\RemoteAccess\ClientObj.cpp(207) : warning C4259: 'unsigned long __stdcall CClientRS::Release(void)' : pure virtual function was not defined
            d:\sourcecodes\remoteaccess\clientrs.h(43) : see declaration of 'Release'
    ClientRS.cpp
    Generating Code...
    Error executing cl.exe.RemoteAccess.dll - 2 error(s), 6 warning(s)
      

  4.   

    你自己实现一下Addref,release,queryinterface,不就可以了啊,呵呵。“pure   virtual   function   was   not   defined”说明你的CClientRS是个抽象类。
      

  5.   

    应该继续调用QueryInterface去查询接口啊,CoCreateInstance已经创建好对象了,就不用再new了。
      

  6.   

    他是不想用CoCreateInstance,而想直接实例化来用。
      

  7.   

    atl类是在实例化时才实现IUnknown接口,像你那样new一个实例,当然会报抽象类不能创建的错误。
    如果你非要像这样使用这个类,那你在客户端包含atl的头文件,模仿类厂的实现,如:#include <atlbase.h>
    #include <atlcom.h>
    #include <atlimpl.cpp>
    .....................
    .....................
       CComObject<CClientRS>* pCClientRS;
       CComObject<CClientRS>::CreateInstance( &pCClientRS );
      

  8.   

    楼上两位仁兄,按照这个错误提示,应该是不能通过直接实例化来创建对象了。
    是不是只能采用CoCreateInstance的方法了。我的程序中结构是这个样子的:
    我想在程序中通过CClientRS的成员函数对CClientRS中的成员变量进行赋值。
    外部用户程序通过调用IClientRS的接口方法从CClientRS中获取数据的。
    所以我自己程序中就不想使用CoCreateInstance构造IClientRS对象,
    也不想使用这个接口对象,想直接使用CClientRS的类对象。如果因为CClientRS是个虚类,不能通过new实例化,
    是不是说我在程序中也只能使用CoCreateInstance创建接口对象,然后通过接口来操作CClientRS的成员变量?
    如果不能通过CClientRS的类对象直接使用其成员变量,那么CClientRS的public的成员函数还有什么用呢?恳请两位仁兄再次指点!谢谢!!
      

  9.   

    你自己实现一下Addref,release,queryinterface,不就可以了啊,呵呵。“pure       virtual       function       was       not       defined”说明你的CClientRS是个抽象类。 
    ---------------
    这不是告诉你了吗?//*************************** IUnknown ***************************
    //
    STDMETHODIMP CScriptHost::QueryInterface(const IID& iid, void **ppv)
    {
        HRESULT hr = S_OK;    if (iid == IID_IUnknown)
        {
            *ppv = (IClientRS *)this;
            ((IClientRS *)(*ppv))->AddRef();
        }
        else if (iid == IClientRS)
        {
            *ppv = (IClientRS *)this;
            ((IClientRS *)(*ppv))->AddRef();
        }
        else
        {
            *ppv = NULL;
            hr = E_NOINTERFACE;
        }//endi    return hr;
    }STDMETHODIMP_(ULONG) CScriptHost::AddRef()
    {
        return 1;
    }STDMETHODIMP_(ULONG) CScriptHost::Release()
    {
        return 1;
    }不过你要记得自己管理new出来的对象的释放。
    比较正常的方法是通过CreateInstance来创建你的com对象,呵呵。
      

  10.   

    yxz_lp:#include <atlbase.h>
    #include <atlcom.h>
    #include <atlimpl.cpp>
    .....................
    .....................
       CComObject<CClientRS>* pCClientRS;
       CComObject<CClientRS>::CreateInstance( &pCClientRS );如果使用按照这种方法实例化的pCClientRS对成员变量操作之后,
    我再使用CoCreateInstance创建IClientRS的接口对象,
    这个接口对象和pCClientRS是不是指向同一个内存空间?
    即我新创建的IClientRS接口对象可否得到刚才pCClientRS对成员变量赋的值?恳请再次指教,谢谢!
      

  11.   

    貌似(我不很确信,很久以前看的,现在记不清楚了),你编写的这些COM的类都是一个中间的类,编写完成后VC会生成一个真正使用的类,从那里来创建这个类,new也是在那个类里面.具体情况还请牛人来介绍一下,俺是不清楚的~~~
      

  12.   

    template <class T1>
    class CComCreator
    {
    public:
    static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
    {
    ATLASSERT(*ppv == NULL);
    HRESULT hRes = E_OUTOFMEMORY;
    T1* p = NULL;
    ATLTRY(p = new T1(pv))
    if (p != NULL)
    {
    p->SetVoid(pv);
    p->InternalFinalConstructAddRef();
    hRes = p->FinalConstruct();
    p->InternalFinalConstructRelease();
    if (hRes == S_OK)
    hRes = p->QueryInterface(riid, ppv);
    if (hRes != S_OK)
    delete p;
    }
    return hRes;
    }
    };这是我跟踪进去后看到的代码,具体的我就不清楚了
      

  13.   

    //Base is the user's class that derives from CComObjectRoot and whatever
    //interfaces the user wants to support on the object
    template <class Base>
    class CComObject : public Base
    {
    public:
    typedef Base _BaseClass;
    CComObject(void* = NULL) //调用完我写的COM类的构造函数后就跳到此处,
                                     //这个类应该就是自己写的COM类的子类,你可以看一下上面的注释
    {
    _Module.Lock();
    } //此方法执行完后就回到了我面的ATLTRY(p = new T1(pv))处,应该new的就是这个类
    别的俺就不看了,太晕,水平不够~~~
      

  14.   

          CComObject <CClientRS> *   pCClientRS; 
          CComObject <CClientRS> ::CreateInstance(   &pCClientRS   ); 
    这样创建了类对象后,就可也用IUnknown的方法查询IClientRS的接口接口了。
    CComPtr<IUnknown> ptrUnk = pCClientRS;
     ptrUnk.QueryInterface()//查询你要的接口。
      

  15.   

    yxz_lp:多谢你的指点,我搞清楚了。
    也感谢以上的各位仁兄,谢谢你们指导!