views:

138

answers:

5

In C# we have a datatype object which can hold any type of data. Same thing I want to achieve in VC++. Can anyone kindly let me know VC++ equivalent of "Object of C#".
IN C#, in the calling appl program (say call.cs)

object ob=null;
ob=(object)str; 
 funct(ref ob);

Here str is empty string.

This thing I want to achieve in VC++. So I need to create VC++ equivalent of object. I am sure we need to use pointers as ref's equivalent??

+3  A: 

There isn't one. C++ doesn't have a unified type hierarchy like .NET languages have.

The closest you can get is a void* (pointer-to-void), which can point to any type of object. You should avoid void*s like the plague, though; once you start using them you lose any and all type safety.

James McNellis
Actually in the above code, "funct(ref ob);", the function definition for this funct(); is present in a COM DLL (in VC++). And the receiving parameter type in the function definition is of VARIANT * type------ funct(VARIANT * z).. If we want to call this function from a C# code than the above code snippet (In my question) can be used. But when I want to call this COM DLL function funct(VARIANT * z) from my VC++ application, how shall I achieve this? Kindly let me know..
@user: I have no idea; I have practically no experience with COM. The `func(ref ob)` syntax is not C++.
James McNellis
Can I create a VARIANT type of VT_BSTR and pass its address as the parameter.. I mean VARIANT collector; collector.vt=VT_BSTR; collector.bstrVal=SysAllocString((OLECHAR *)" "); and finally call the funct() as, -----------funct( ......
@user: When I said I have practically no experience with COM, I really meant it. I don't know. Someone else might, though.
James McNellis
Ok James no problem.. Thanks..
+4  A: 

There's nothing built into the language. Usually, wanting it at all indicates that your design isn't very well thought out, but if you can't figure out any alternative, you might consider (for one example) Boost any.

Jerry Coffin
A: 

The alternative for you is to look at System.Runtime.InteropServices.GCHandle, which allows you to find the managed object from unmanaged code, but in any way you will end up with nasty and risky type casts and you need to be really careful to keep somewhere a reference to the managed object as it might get garbage-collected if there is only a reference in unmanaged code.

weismat
+1  A: 

The <comutil.h> header contains a handy wrapper for VARIANT. Takes care of proper initialization and cleanup.

#include <comutil.h>
#ifdef _DEBUG
#  pragma comment(lib, "comsuppwd.lib")
#else
#  pragma comment(lib, "comsuppw.lib")
#endif
...
    _variant_t arg = L"some string";
    someComPtr->func(&arg);

There isn't anything in your code snippet that would help me help you figuring out how to obtain the COM interface pointer. Start a new question about that if you have trouble.

Hans Passant
A: 

As other commentators have said, C++ does not have a common base-class for every object. Theoretically, you could create your own and derive everything from it:

class Object
{
protected:
    Object(){};
    virtual ~Object(){};

public:
    virtual std::string toString() const {return("");};
}; // eo class Object

This, however, won't help you with integral types such as int, short. You'd have to make your own:

class Int : public Object
{
private:
    int m_nVal;

public:
    Int(int _val = 0) : m_nVal(_val){};
    Int(const Int& _rhs) : m_nVal(_rhs.m_nVal){};
    virtual ~Int(){};

    // operators
    operator int() const {return(m_nVal);}
    bool operator == (const Int& _rhs) const {return(m_nVal == _rhs.m_nVal);};
    bool operator == (int _val) const {return(m_nVal == _val);};
    Int& operator = (const Int& _rhs) {m_nVal = _rhs.m_nVal; return(*this);}:
    Int& operator = (int _val) {m_nVal = _val; return(*this);};
    // .... and all the other operators

    // overrides
    virtual std::string toString() const
    {
       std::ostringstream oss;
       oss << m_nVal;
       return(oss.str());
    };
}; // eo class Int

You'd then have to do this for all the other types you want to use. Once done you can pass them around as if they were ints, bools, longs etc (thanks to operator overloading). A better method would be to use a template class for the integral types:

template<class T> class IntegralType : public Object
{
private:
    T m_Val;

public:
    // rest of class looks the same
}; // eo class IntegralType<>

Then typedef them away:

typedef IntegralType<int> Int;
typedef IntegralType<short> Short;
typedef IntegralType<long> Long;

Even using a template-class like this to take the leg-work out of it, you'd still need a specialisation for strings/bools. implementing operator ++ on IntegralType<> will work fine for numbers, but is going to throw up on std::string.

If you went the template route, you've now got "Object", integral types and some specialisations for strings, bools. But to mimick .NET even more, you probably want to introduce interfaces for comparisons:

template<class T> class IEquitable
{
public:
    virtual Equals(T _other) = 0;
};   // eo class IEquitable<>

That can easily be plumbed in to your IntegralType<> classes and the specialisations.

But as another commentator pointed out, why would you? boost::any is useful if you're trying to do something like a Tuple which has a name and a value of an arbitrary type. If you need to build a collection of these then there is something fundamentally wrong with your design. For example, in all my coding in C# I have never had to write:

List<Object> list = new List<Object>();

There may have been:

List<Vehicle> list;
List<Employee> List;
Dictionary<string, Alien> aliens;

But never anything at the Object level. Why? Well apart from calling ToString() on it, or perhaps doing some risky casting, why would you want to? Generics exist in programming so that we do not have to have lists of objects (or in the case of C++, void*).

So there you have it. The above shows how you might have objects and integral types working kind of like C#, and I've missed a chunk of stuff out. Now it's time to look at your design and decide if that's what you really need to do.

Moo-Juice