I'm working in Visual Studio 2005 with a pure unmanaged project (C++). I have a COM class, from a third party, in a OCX file. This class is a control ("widget"). I've been using it through a IDispatch wrapper class generated using the Add Class from Typelib Wizard.
I would like to extend this class in a few ways and public inheritance would be way more practical than compositing (I want the derived object to expose every single method that the parent class does). The derived class should also be available as a COM component.
Can I do this? If positive, how can I accomplish this?
It is not possible to inherit from COM classes as you can in C++. There are workarounds though:
COM Aggregates
Forwarding
COM aggregates is only useful if you want to add an interface (with implementation) to an existing COM class. You cannot intercept calls to the aggregated object.
Forwarding means that if you have an interface IExistingInterface, you implement your own class that implements IExistingInterface. In your class you keep a reference to an instance of the object you want to "inherit" from. In your implementation of IExistingInterface, you forward calls as appropriate to the "inherited" object. This method gives you total control.
Example: (pseudo-code!)
class MyClass : IExistingInterface {
IExistingInterface* m_pInherited;
public:
MyClass() {
::CoCreateInstance(CLSID_OtherImplementation, ..., ..., IID_IExistingInterface, (void**)&m_pInherited);
}
// IExistingInterface methods
HRESULT MethodX() {
// Do some pre processing
HRESULT hr = m_pInherited->MethodX();
if(FAILED(hr))
return hr;
// Do some post processing
return S_OK;
}
};
Edit:
I really recommend that you use ATL to create your COM component. In that case, construct the "inherited" object in FinalConstruct() rather than the C++ constructor.
You can create a new interface that derives from the first. Your QueryInterface function will need to respond to both GUIDs and deliver the proper pointer. Once you've done that, have your concrete class implement the superset of the functions (i.e. all of the second interface, including everything inherited from the first.)
If your concrete class will also inherit from a concrete class in the library, you're going to have a diamond inheritance pattern. You can search for solutions to that, I'd start here: Diamond inheritance (C++)
Related
I am trying to implement shared logic using COM aggregation with ATL. I've defined a base class, called CameraBase, that is only available through aggregation. Therefor I've added the aggregateable annotation to it's coclass-declaration.
[
uuid(...),
aggregatable
]
coclass CameraBase
{
[default] interface ICamera;
};
I've also added the DECLARE_ONLY_AGGREGATEABLE macro to the class definition.
class ATL_NO_VTABLE CCameraBase :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CCameraBase, &CLSID_CameraBase>,
public ISupportErrorInfo,
public IProvideClassInfoImpl<...>,
public IDispatchImpl<...>
{
public:
CCameraBase()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_CAMERABASE)
DECLARE_ONLY_AGGREGATABLE(CCameraBase)
BEGIN_COM_MAP(CCameraBase)
...
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
...
}
Now I have different classes who are using the logic of CameraBase somewhere. Therefor I've extented the com map of the parent class (e.g. SampleCamera):
BEGIN_COM_MAP(CSampleCamera)
COM_INTERFACE_ENTRY_AGGREGATE(IID_ICamera, m_base)
...
END_COM_MAP
DECLARE_GET_CONTROLLING_UNKNOWN()
Since I want to be able to call the members on CameraBase (through the ICamera interface) from the parent class, I do not want to use COM_INTERFACE_ENTRY_AUTOAGGREGATE, which stores the inner object's pointer as a reference of IUnknown. Therefor I am creating it on my own from the FinalConstruct-method:
HRESULT FinalConstruct()
{
HRESULT hr;
if (FAILED(hr = m_camera.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)))
return hr;
}
Where m_camera is defined as CComPtr<ICamera>. However, this does result in a error CLASS_E_NOAGGREGATION (HRESULT 0x80040110). My current workaround is to store two references, IUnknown and ICamera, and query for the later one.
if (FAILED(hr = m_base.CoCreateInstance(CLSID_CameraBase, this->GetControllingUnknown(), CLSCTX_INPROC_SERVER)) ||
FAILED(hr = m_base->QueryInterface(&m_camera)))
return hr;
This works, but it feels kinda strange, since the class (CameraBase) that get's instanciated is the same in both cases. Am I missing something? Am I using the right way to aggregate the inner object? Why does the returned pointer of CoCreateInstance need to be of type IUnknown, if an outer unknown is passed?
Thanks in advance! :)
An aggregatable COM object provides two distinct implementations of IUnknown - non-delegating and delegating.
The non-delegating implementation is the "normal" one - its QueryInterface hands out interfaces implemented by the aggregatable object, and its AddRef and Release control the lifetime of that object.
The delegating implementation, as the name suggests, delegates all three method calls to the controlling IUnknown of the outer object. All the other interfaces implemented by the object have their three IUnknown methods backed by this delegating implementation. This is how the aggregation can maintain an illusion for the client that it's dealing with a single COM object - it allows the client to query from an interface implemented by the outer to one implemented by the inner, and (more interestingly) vice versa. Recall that it's a requirement for IUnknown that QueryInterface implementation be symmetrical and transitive.
When CoCreateInstance is called with non-NULL controlling unknown parameter, it must request IUnknown from the inner object - that is the outer's one and only chance to obtain a non-delegating implementation. You cannot use any other interface pointer from the inner in the outer's interface map - again, all other interfaces are backed by a delegating unknown, so forwarding QueryInterface call to them would end up calling QueryInterface on the outer, and end up right back in the interface map, leading to an infinite recursion.
I am looking into DirectShow samples from Windows SDK. Many of the classes feature non-default constructor. How those constructors are called? Who supplies arguments?
Can I use those classes in C++ programs without registration? If so I could use class constructor directly.
If I use a COM class without registration what happens in the following code fragment:
Foo * foo = new Foo(.....); // note, not using CoCreateInstance
Bar * bar = foo->QueryInterface(...);
bar->Release();
delete foo; // CRASH?
Thank you!
It has nothing to do with COM, it is just the framework is built this way and constructor arguments in DirectShow BaseClasses are necessary to get everything together - the class, the ancestor, the instantiating factory.
Using COM class without registration might be or might not be possible. I suspect you might be interested in using DirectShow filter without registration instead, and there is a good article on the topic: Using Filters Without Registration.
A C++ class that's exposed as a real COM coclass cannot in general have a constructor that takes arguments. There's no mechanism for the COM client code to pass arguments to the CoCreateInstance() function. A COM interface typically has an Initialize() method to supply required initialization. Technically that can be doctored as well, CoCreateInstance is just a convenience function that hides the class factory (IClassFactory). A custom class factory with a custom CreateInstance() method is possible, but rarely done.
Microsoft uses the interface-based programming model that's common in COM code in non-COM code as well. DirectX is a good example. Think of Direct3DCreate9Ex() as the class factory.
I am relatively new to "design patterns" as they are referred to in a formal sense. I've not been a professional for very long, so I'm pretty new to this.
We've got a pure virtual interface base class. This interface class is obviously to provide the definition of what functionality its derived children are supposed to do. The current use and situation in the software dictates what type of derived child we want to use, so I recommended creating a wrapper that will communicate which type of derived child we want and return a Base pointer that points to a new derived object. This wrapper, to my understanding, is a factory.
Well, a colleague of mine created a static function in the Base class to act as the factory. This causes me trouble for two reasons. First, it seems to break the interface nature of the Base class. It feels wrong to me that the interface would itself need to have knowledge of the children derived from it.
Secondly, it causes more problems when I try to re-use the Base class across two different Qt projects. One project is where I am implementing the first (and probably only real implementation for this one class... though i want to use the same method for two other features that will have several different derived classes) derived class and the second is the actual application where my code will eventually be used. My colleague has created a derived class to act as a tester for the real application while I code my part. This means that I've got to add his headers and cpp files to my project, and that just seems wrong since I'm not even using his code for the project while I implement my part (but he will use mine when it is finished).
Am I correct in thinking that the factory really needs to be a wrapper around the Base class rather than the Base acting as the factory?
You do NOT want to use your interface class as the factory class. For one, if it is a true interface class, there is no implementation. Second, if the interface class does have some implementation defined (in addition to the pure virtual functions), making a static factory method now forces the base class to be recompiled every time you add a child class implementation.
The best way to implement the factory pattern is to have your interface class separate from your factory.
A very simple (and incomplete) example is below:
class MyInterface
{
public:
virtual void MyFunc() = 0;
};
class MyImplementation : public MyInterface
{
public:
virtual void MyFunc() {}
};
class MyFactory
{
public:
static MyInterface* CreateImplementation(...);
};
I'd have to agree with you. Probably one of the most important principles of object oriented programming is to have a single responsibility for the scope of a piece of code (whether it's a method, class or namespace). In your case, your base class serves the purpose of defining an interface. Adding a factory method to that class, violates that principle, opening the door to a world of shi... trouble.
Yes, a static factory method in the interface (base class) requires it to have knowledge of all possible instantiations. That way, you don't get any of the flexibility the Factory Method pattern is intended to bring.
The Factory should be an independent piece of code, used by client code to create instances. You have to decide somewhere in your program what concrete instance to create. Factory Method allows you to avoid having the same decision spread out through your client code. If later you want to change the implementation (or e.g. for testing), you have just one place to edit: this may be e.g. a simple global change, through conditional compilation (usually for tests), or even via a dependency injection configuration file.
Be careful about how client code communicates what kind of implementation it wants: that's not an uncommon way of reintroducing the dependencies factories are meant to hide.
It's not uncommon to see factory member functions in a class, but it makes my eyes bleed. Often their use have been mixed up with the functionality of the named constructor idiom. Moving the creation function(s) to a separate factory class will buy you more flexibility also to swap factories during testing.
When the interface is just for hiding the implementation details and there will be only one implementation of the Base interface ever, it could be ok to couple them. In that case, the factory function is just a new name for the constructor of the actual implementation.
However, that case is rare. Except when explicit designed having only one implementation ever, you are better off to assume that multiple implementations will exist at some point in time, if only for testing (as you discovered).
So usually it is better to split the Factory part into a separate class.
I'm writing an ATL project and I wonder how should I create classes here.
Right now I have one class created by Add/Class/ATL Simple Object. I want to divide it to smaller classes but method from this classes should use CComPtr and have CComPtr as an argument. I can't create 'simple' c++ class because I don't have CComPtr there.
Should I create ATL classes by ATL Simple Object Wizard and then use interface for this class to call methods. Like here:
CComPtr<ITestAtlClass> tptr;
tptr.CoCreateInstance(CLSID_TestAtlClass);
tptr->test();
And should I add all public methods by Class View/ITestAtlClass/Add/Add Method?
What about constructors? Do I must initialize my class only by properties (and add them by Class View/ITestAtlClass/Add/Add Property)? And pass every com object by IUnknown interface?
Can somebody tell me how it should be done in ATL project. I will use this smaller classes internally (nobody will create this classes outside my DLL) just to make my code more readable.
I don't understand your comment that you can't use CComPtr from a simple C++ class. Can you please clarify?
I see two strategies:
build a clean C++ object model that solves the problem, and then wrap it in a thin facade layer of one or more COM objects
Use ATL classes throughout, and use CComObject<> and derivatives to instantiate and maintain these without the overhead of CoCreateInstance and the limitations of only using public interfaces.
The first one is usually much nicer, but if you're building a data-heavy object model, the second can be a useful technique.
If you have an ATL COM class called CVehicle, that derives from CComObjectRootEx<> and friends, you can instantiate it like so;
CComObject<CVehicle>* vehicle = NULL;
CComObject<CVehicle>::CreateInstance(&vehicle);
vehicle->AddRef();
// To get at any of its interfaces, use:
CComPtr<ICar> car = 0;
vehicle->QueryInterface(&car);
// And to delete object, use:
vehicle->Release();
There's also variations on CComObject<>, e.g. CComObjectStack<> that use different allocation and reference counting strategies.
As you can see, this is pretty messy. If you can explain what you mean by your comment on not being able to use CComPtr, maybe I can expand on that.
I'm working on implementing a Factory class along the lines of what is proposed in this response to a previous question:
Factory method implementation - C++
It's a Factory that stores a map from strings to object creation functions so I can request different types of objects from the factory by a string identifier. All the classes this factory produces will inherit from an abstract class (Connection) providing a common interface for connections over different protocols (HTTPConnection, FTPConnection, etc...)
I have a good grasp of how the method linked to above works and have got that working.
Where I'm having problems is trying to figure out a mechanism to prevent instantiation of the Connection objects without using the Factory. In order for the Factory to do it's work, I need to provide it an object creation function to store in it's map. I can't provide it the constructor because you can't make function pointers to constructors. So, as in the link above, there has to be a seperate object creation function to return new objects. But to do this, I need to make this creation function either a static method of the class, which the client code would be able to access, or a seperate function which would require either a)that the constructor of the Connection classes be public, or b) make the constructor private and make a non class member creation function be a friend, which isn't inherited and can't be enforced by the abstract base class.
Similarly, if I just made the Factory class friends with the Connection classes it was supposed to produce so it could access their private constructors, that would work, but I couldn't enforce through the abstact base class because friends aren't inherited. Each subclass would have to explicitly be friends with the Factory.
Can anyone suggest a method of implementing what I've described above?
To reiterate the requirements:
1 - Factory that produces a variety of objects all derived from the same base class based on passed in identifier to the Factory's Create method.
2 - All the subclasses that the factory will need to produce will automatically register a creation function and identifier with the factory (see linked SO answer above)
3 - All the subclasses that the factory will produce should not be instantiable (instantiatable?) without going through the Factory
4 - Enforce #3 explicitly as part of the abstract base class using inheritance. Remove the possibility for someone to subclass from the abstract base class while also providing mechanisms to freely instantiate objects.
The overall goal of what I'm trying to achieve is to allow new Connection types to be added to the hierarchy without having to change the Factory class in any way, while also forcing all the subclasses of Connection to not be instantiable directly by client code.
I'm open to the possibility that this is not the best way to achieve what I want, and suggestions of other alternatives are welcome.
EDIT - Will add some code snippets to this when I get home to hopefully make this clearer.
If I understand you correctly I think you can put some of what you want in the METADECL macro I mention in my answer you link to, ie define a static creator function that is a friend or declare it as a static method. This will make it possible for you to restrict the constructor from public use etc.
Below I try to point out where the METADECL (and METAIMPL) should be. I leave it for you to implement what you need there (I believe in you)
Header file
class MySubClass : public FactoryObjectsRoot {
METADECL(MySubClass) // Declare necessary factory construct
:
:
};
Source file
METAIMPL(MySubClass) // Implement and bootstrap factory construct