-
Instantiate abstract class
Hi all,
I have a class, CCollection, which holds a number of CConnection objects. CCollection and CConnection are interfaces for a COM object.
I want to use pointers, but when I want to create a new object, I receive this error:
error C2259: 'CConnection' : cannot instantiate abstract class due to following members:
warning C4259: 'long __stdcall CConnection::QueryInterface(const struct _GUID &,void ** )' : pure virtual function was not defined
It happens with this code:
CConnection * pTemp = new CConnection(parameters);
I looked up in the help what this error means, but it still isn't clear to me. If I try to overwrite this function, the compiler says the function is already declared.
Any idea how to fix this error??
Thanks!
-
Re: Instantiate abstract class
You cannot instantiate an abstract class as you already experience...you need to provide implementations for all pure virtual functions....for further information take a look at the following FAQs:
-
Re: Instantiate abstract class
Quote:
Originally Posted by Andreas Masur
You cannot instantiate an abstract class as you already experience...you need to provide implementations for all pure virtual functions....for further information take a look at the following FAQs:
So, when I implement those functions, I am able to instantiate the class? Or do I understand you wrong?
If I am right, how and where can I implement those functions, because when I am trying to overwrite them, the compiler says I have already defined the function.
I'll take a look at the links you gave me! Thanks!
-
Re: Instantiate abstract class
Quote:
Originally Posted by Tischnoetentoet
If I am right, how and where can I implement those functions, because when I am trying to overwrite them, the compiler says I have already defined the function.
The pure virtual functions are to be implemented in derived classes. If one derived class ( regardless of its level in the hierarchy) implements all the pure virtual functions it becomes a concrete class and can be instantiated. Otherwise it is an abstract class and cannot be instantiated.
-
Re: Instantiate abstract class
One more point ....
Here the class being instantiated is COM object, so you need to implement the provided abstract functions within the class .
AddRef()
QueryInterface()
....
-
Re: Instantiate abstract class
Thanks a lot!
I'll try to fix it! Thanks!
-
Re: Instantiate abstract class
Ok, here is what I did:
I added this code to my CConnection class to implement the functions:
Code:
unsigned long CConnection::AddRef()
{
return 0;
}
//=====================================================================
HRESULT CConnection::QueryInterface(REFIID riid, void** ppv)
{
// Call original function
return S_OK;//IConnection::QueryInterface(riid, ppv);
}
//=====================================================================
ULONG CConnection::Release()
{
return 0;
}
These are the errors I get now:
Code:
Collection.cpp(105) : error C2259: 'CConnection' : cannot instantiate abstract class due to following members:
connection.h(27) : see declaration of 'CConnection'
Collection.cpp(105) : warning C4259: 'long __stdcall CConnection::QueryInterface(const struct _GUID &,void ** )' : pure virtual function was not defined
connection.h(43) : see declaration of 'QueryInterface'
Collection.cpp(105) : warning C4259: 'unsigned long __stdcall CConnection::AddRef(void)' : pure virtual function was not defined
connection.h(43) : see declaration of 'AddRef'
Collection.cpp(105) : warning C4259: 'unsigned long __stdcall CConnection::Release(void)' : pure virtual function was not defined
connection.h(43) : see declaration of 'Release'
Collection.cpp(107) : error C2259: 'CConnection' : cannot instantiate abstract class due to following members:
connection.h(27) : see declaration of 'CConnection'
Collection.cpp(107) : warning C4259: 'long __stdcall CConnection::QueryInterface(const struct _GUID &,void ** )' : pure virtual function was not defined
connection.h(43) : see declaration of 'QueryInterface'
Collection.cpp(107) : warning C4259: 'unsigned long __stdcall CConnection::AddRef(void)' : pure virtual function was not defined
connection.h(43) : see declaration of 'AddRef'
Collection.cpp(107) : warning C4259: 'unsigned long __stdcall CConnection::Release(void)' : pure virtual function was not defined
connection.h(43) : see declaration of 'Release'
Any idea what's wrong now??
-
Re: Instantiate abstract class
You never told us you were trying to write a COM object !! I presume this is inside of a dll :
Use the ATL wizards to create COM objects and add methods to them. Don't try to do them by hand unless you REALLY know what you're doing.
What exactly is CConnection ? I take it you've got an IConnection interface.
Darwen.
-
Re: Instantiate abstract class
Quote:
What exactly is CConnection ? I take it you've got an IConnection interface.
Yes, you are right! It is an interface. A short description what my COM object must do:
I want a connection with a PLC (Programmable Logic Controller). The communication for 1 PLC is done by CConnection.
I have made a collection class (CCollection) which can hold up to 128 CConnection objects. This way the user is able to connect with several PLC's with one COM object.
I can communicate with my COM object (ICollection). But when I want to add a new object of CConnection to the array of connections, these errors occurres...
I hope it's clear to you now!
Thanks so far!
-
Re: Instantiate abstract class
CConnection is an abstract base class. You cannot instantiate it. You need to derive a class from it and override the pure virtual functions in your derived class.
-
Re: Instantiate abstract class
Quote:
Originally Posted by GCDEF
CConnection is an abstract base class. You cannot instantiate it. You need to derive a class from it and override the pure virtual functions in your derived class.
After implementing the abstract function in your derived class, you can instantiate the derived class, and make use of that.
-
Re: Instantiate abstract class
But I didn't even declare the functions AddRef, Release and QueryInterface myself!
Why would a class derived from CConnection work, but CConnection itself not?
Maybe you can explain me?
-
Re: Instantiate abstract class
Quote:
Originally Posted by Tischnoetentoet
But I didn't even declare the functions AddRef, Release and QueryInterface myself!
Why would a class derived from CConnection work, but CConnection itself not?
Maybe you can explain me?
That's the way pure virtual functions and abstract base classes work. It's part of the language.
-
Re: Instantiate abstract class
so if I do this, it should work?
Code:
class CConnectionImpl : public CConnection
{
public:
// Constructor & destructor
CConnectionImpl();
~CConnectionImpl();
// Functions
// Variables
private:
// Functions
HRESULT QueryInterface(RIID, void**)
{
// Implementation
}
ULONG AddRef()
{
// Implementation
}
ULONG Release()
{
// Implementation
}
// Variables
}
Just copy the whole class, but implement the 3 functions. Is that all?
-
Re: Instantiate abstract class
Quote:
Originally Posted by Tischnoetentoet
so if I do this, it should work?
Code:
class CConnectionImpl : public CConnection
{
public:
// Constructor & destructor
CConnectionImpl();
~CConnectionImpl();
// Functions
// Variables
private:
// Functions
HRESULT QueryInterface(RIID, void**)
{
// Implementation
}
ULONG AddRef()
{
// Implementation
}
ULONG Release()
{
// Implementation
}
// Variables
}
Just copy the whole class, but implement the 3 functions. Is that all?
Not sure what you mean "copy the whole class". You create a new class derived from CConnection and implement only the functions you need to, which in this case seems to be the pure vitrual ones. You don't need to recreate all the variables and other functions whose behavior you don't want to change.
-
Re: Instantiate abstract class
yes.. that's what I ment... (or meant)
But I don't understand. Why would a derived class of a derived class work? But a derived class would not work?!
The CConnection class is already a derived class of class (interface) IConnection and some atl class (which I think have defined the pure virtual functions).
-
Re: Instantiate abstract class
Quote:
Originally Posted by Tischnoetentoet
yes.. that's what I ment... (or meant)
But I don't understand. Why would a derived class of a derived class work? But a derived class would not work?!
The CConnection class is already a derived class of class (interface) IConnection and some atl class (which I think have defined the pure virtual functions).
Your original post makes it appear that CConnection has the pure virtual functions.
Regardless, you can't instantiate a class until you've provided implementations of the pure virtual functions.
-
Re: Instantiate abstract class
In actual fact ATL classes are NOT designed to be derived from. They are designed to be CoCreateInstance-d and therefore if you derive from them your derived class will never be used because client's won't have access to it.
Obviously this is not strictly true : you can do some clever stuff with CoGetClassObject to return the derived class but why would you want to do this ?
So the question needs to be asked : why are you trying to derive from an ATL COM-object class in the first place ? You're not really going to get any benefit from doing this.
Darwen.
-
Re: Instantiate abstract class
Why are you trying to instatiate a COM object?? You get an interface to a COM class and let the COM framework instatiate the class. Your code should look like this:
Code:
CComPtr<IConnection> pTemp;
pTemp.CoCreateInstance( CLSID_CConnection );
IConnection is the name of the interface and CLSID_CConection is the CLSID of the COM interface. Then call your methods off the interface. Do not try to instatiate a COM class yourself (and remove the changes you made to AddRef, Release, and QueryInterface).
-
Re: Instantiate abstract class
Hi,
Thanks for all the replies.
Quote:
So the question needs to be asked : why are you trying to derive from an ATL COM-object class in the first place ? You're not really going to get any benefit from doing this.
I don't want to create pointers in my client, but in my server (COM object itself). The COM object has an interface IConnection which is responsible for 1 connection. It also has an interface CCollection which is responsible for storing several connections.
That's the reason why I want to instantiate the class. It should be possible to have more connections in one COM object, isn't it???
-
Re: Instantiate abstract class
Hang on - CCollection is an interface ? Why didn't you make it IConnectionCollection or something.
I'm starting to get really confused here. Either CCollection is a class or it's an interface - one or the other. It can't be both. So which one is it ?
Oh and if you want more than one connection CoCreateInstance it from inside of your dll. That's the safest way of doing it.
There are other ways (like the static CComObject<>::CreateInstance) but this I would suggest is the best for you.
So why don't you have an IConnectionConnection interface to an CConnectionCollection class (created using the ATL wizard). Inside of this you'd have an array (as a member) containing IConnection interfaces. These will have been CoCreateInstanced by your CConnectionCollection class as and when it feels like it.
I really don't think you quite understand the difference between an interface and a COM object. A COM object isn't an interface. A COM object HAS interfaces.
Darwen.
-
Re: Instantiate abstract class
whoops!
that is a type mistake, which is not very smart of me! I am very sorry! Of course the CCollection is an interface, but it's real class name is ICollection.
I'll try the CoCreateInstance solution...
Thanks for you answer, and I am sorry I confused you a lot!
-
Re: Instantiate abstract class
ok, searched in the help for the function CoCreateInstance. Help says you should use this function if you want only one object on the same computer.
However, I need more instances, so I kept searching, and find the function CoGetClassObject. The help says you have to use this function when you want more instances of a class on the same computer.
So, with this information, I decided to use the CoGetClassObject function. I wrote a function AddConnection. However, the return value is always NULL.
Code:
// Declare variables
LPVOID pInterfacePointer;
// Create the object
if (CoGetClassObject(CLSID_Connection,
CLSCTX_INPROC_HANDLER,
NULL,
IID_IConnection,
&pInterfacePointer) != S_OK)
{
// It failed!
}
// Add new object to array of connections
m_arrConnections[m_iConnectionCount++] = (IConnection * )pInterfacePointer;
// Init object
m_arrConnections[m_iConnectionCount-1]->Init(ip, port, name);
The strange thing is that the function CoGetClassObject is returning S_OK, but pInterfacePointer is NULL. How is this possible?
And do you think I have the right function now?
Thanks!
-
Re: Instantiate abstract class
CoGetClassObject is usually used to get the IClassFactory interface for your object. This is the implementation of the class factory of your object which is responsible for creating the instances. In actual fact you're using it the wrong way : it doesn't create an instance of your object, it creates a class factory for your object.
Where'd you get the fact that you should only use CoCreateInstance once per object instance ?
Actually you can use it as many times as possible. The CoGetClassObject route is really just an optimisation : and it really only comes into force if you're creating thousands of like COM objects.
I've never used it personally and have always used to CoCreateInstance COM objects with no perceivable speed impact.
Darwen.
-
Re: Instantiate abstract class
Quote:
Where'd you get the fact that you should only use CoCreateInstance once per object instance ?
Quote from MSDN:
Quote:
CoCreateInstance
Creates a single uninitialized object of the class associated with a specified CLSID. Call CoCreateInstance when you want to create only one object on the local system. To create a single object on a remote system, call CoCreateInstanceEx. To create multiple objects based on a single CLSID, refer to the CoGetClassObject function.
But I'll try the CoCreateInstance functions as you say!
I'll let you know if it works!
Thanks again!
-
Re: Instantiate abstract class
It works perfect!
No compile errors, and I can really create instances of the IConnection interface!
Thanks a lot!
There is one last question. Do I have to delete this object myself with delete?
-
Re: Instantiate abstract class
You have to release the object by calling it's Release() method.
Never delete COM objects directly : call their Release() methods instead.
Darwen.
-
Re: Instantiate abstract class
ok, thanks you very much for your help!
I really appreciate it!