Допустим у вас есть некоторое приложение, написанное на C++(VC++ если быть корректным). Как оно у вас появилось не суть важно, может быть это ваша старая разработка, может быть,  вы решили сначала  отладить предметную часть. Важно то что вы горите желанием  вынести часть классов в объектные модули и оформить  их в виде ActiveX, COM и ATL объектов.  Есть несколько типовых проблем связанных с таким переносом.
Множественные конструкторы.
class MyCOM 
{
   MyCOM();
   MyCOM(long id);
   MyCOM(long id, LPCSTR Name);
}
  Знакомо и очень удобно, но в COM правила создания объекта строго определены и  ни одна из функции  для созданий объектов не позволяет передавать параметры конструктору класса.
Настройку объекта придется  вынести в отдельный метод, например Init.
   // IMyCOM стандартная обертка наследник от COleDispatchDriver
   IMyCOM * d=new IMyCOM;
   COleException pErr; 
   CString SSS="Mylib.MyCOM";
   d->CreateDispatch( SSS,&pErr);
   d->Init(15,Матрица); // Инициализируем
  В принципе вы можете создать свою фабрику объектов. Это позволит создавать объекты  вот так.
   IMyOF * d=new IMyOF;
   COleException pErr; 
   CString SSS="MyLib.MyOF";
   d->CreateDispatch( SSS,&pErr);
   IMyCOM  Ob1(d->CreateEmpty());
   IMyCOM  Ob2(d->CreateId(15));
   IMyCOM  Ob3(d->CreateFull(15,SSS ));
Но зачем вам лишний промежуточный объект если можно обойтись без него.  
Перегруженные методы.
class MyCOM 
{
   LPCSTR GetMyRec(long id);
   LPCSTR GetMyRec(LPCSTR Name);
   AddRec ();
   AddRec (long id);
   AddRec (long id, LPCSTR Name);
} 
Это вполне законный код С++, но COM не разрешит вам в  интерфейсе объявить  два метода с одним именем. Это противоречит концепции.
Решение: Можно связать функции с разными методами интерфейса для этого в odl пишим
   [id(1)] BSTR AddRecName(BSTR ID);
   [id(2)] BSTR AddRecID(long ID);
а в cpp осуществляем привязку.
   BEGIN_DISPATCH_MAP(.)
   DISP_FUNCTION(CPSDG, "AddRecName", AddRec, VTS_BSTR, VTS_BSTR)
   DISP_FUNCTION(CPSDG, "AddRecId", AddRec, VTS_BSTR, VTS_I2)
   DISP_FUNCTION_ID(.)
   END_DISPATCH_MAP()
Можно написать  прокси функции. Например, для  GetMyRec прототип может выглядеть так
LPCSTR GetMyRec (VARIANT id)
{
   switch id.vt
   {
    case VT_I4: 
       return GetMyRec(id.lVal); 
    case VT_BSTR: 
       return GetMyRec(id.bstrVal); 	
   }
   return S_OK;
}
Для функции AddRec  можно сделать вот так
HRESULT  AddRec (VARIANT id, VARIANT Name)
{
   if ((id.vt==VT_EMPTY) && (Name.vt==VT_EMPTY))
   {
      AddRec() ; 
      return S_OK;
   }
   if ((id.vt==VT_I4) && (Name.vt==VT_EMPTY))
   {
       AddRec(id.lVal) ; 
       return S_OK;
   }
   if ((id.vt==VT_I4) && (Name.vt== VT_BSTR))
   {
       AddRec(id.lVal, Name. bstrVal ) ; 
       return S_OK;
   }
}
 Этого вполне достаточно, но можно еще изменить объявление метода интерфейса в odl вот так
   HRESULT Add(VARIANT [optional, in]id, [optional,in]VARIANT S);
это позволит вызывать метод, более красиво.
Пример на  VB
   MyObject.Add  // Любой из вариантов должен работать 
   MyObject.Add 15
   MyObject.Add 15, Var
Пользовательские типы данных
В сложном проекте полно собственных констант, структур, множеств используемых в качестве параметров. 
#define IDL_NEXT 5
#define IDL_STOP 6
struct UDT 
 {
      unsigned long X;
      unsigned long Y;
      BSTR pbstr;
  } UDT;
typedef enum EnumType
{
	First=1,
	Seond=4,
	Last =10
};
class MyCOM 
{
   / .
   void SetType (EnumType  T);
   void  Do(UDT  * Dat);
   void SetMove (int val);
   / .
}
// а где-то все это вызывается
   SetType(First);
   UDT  Dat,Dat1;
   Do (&Dat,Dat1);
   SetMove (IDL_NEXT);
Понятно что, для того чтобы подобным образом можно было вызывать методы COM объекта, служебные структуры, множества и константы должны быть доступны из вне. Для этого нужно  включить их описание в ODL файл. Множества описываются так.
[ 
    uuid(...), 
    version(1.0),
    helpstring("...")
]
library LibraryName
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
    typedef enum
    {
        valueName1    = 0,
        valueName2    = 1,
        ...
        valueNameN    = N
    } EnumType;
..
}
Передавать в качестве параметров  структуры тоже можно. Такие структуры называются UDT - User Defined Type. В IDL  описываются так: 
typedef [uuid(C1D3A8C0-A4AA-11D0-819C-00A0C90FFFC3)] struct UDT 
{
   unsigned long X;
   unsigned long Y;
   BSTR pbstr;
}  UDT;
Описывать параметры метода можно как VARIANT но тогда придется работать с интерфейсом IRecordInfo или как UDT: 
   Do([in]UDT* pIn, [in,out] pOut);
Передать UDT в такой метод проще простого:
 
UDT some_data, some_returned_data;
   p->Do(&some_data, some_returned_data);
Членами UDT могут быть другие UDT или oleautomation-совместимые типы. Увы в VC нет автоматизации позволяющей создавать пользовательские типы поэтом у все придется делать ручками.
Пока все дальше будет больше.