Что такое эквивалент «объекта C #» в VC ++? - PullRequest
2 голосов
/ 26 октября 2010

В C # у нас есть объект типа данных, который может содержать данные любого типа. То же самое я хочу достичь в VC ++. Может ли кто-нибудь любезно сообщить мне VC ++ эквивалент "Объекта C #".
В C #, в вызывающей программе appl (скажем, call.cs)

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

Здесь str - пустая строка.

Этого я хочу добиться в VC ++. Поэтому мне нужно создать VC ++ эквивалент объекта. Я уверен, что мы должны использовать указатели в качестве эквивалента ссылки?

Ответы [ 5 ]

8 голосов
/ 26 октября 2010

Нет ни одного. В C ++ нет унифицированной иерархии типов, как в языках .NET.

Самое близкое, что вы можете получить - void* (указатель на пустоту), который может указывать на любой тип объекта. Вы должны избегать void* s, как чума, хотя; как только вы начнете их использовать, вы потеряете все типы безопасности.

6 голосов
/ 28 октября 2010

Как говорили другие комментаторы, C ++ не имеет общего базового класса для каждого объекта. Теоретически, вы можете создать свой собственный и извлечь из него все:

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

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

Это, однако, не поможет вам с целочисленными типами, такими как int, short. Вы должны сделать свой собственный:

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

Тогда вам придется сделать это для всех других типов, которые вы хотите использовать. После этого вы можете передать их, как если бы они были целыми числами, bools, longs и т. Д. (Благодаря перегрузке оператора). Лучшим методом было бы использовать шаблонный класс для целочисленных типов:

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

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

Затем напечатайте их:

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

Даже если использовать шаблонный класс, подобный этому, чтобы избавиться от лишнего труда, вам все равно понадобится специализация для строк / bools. Реализация оператора ++ на IntegralType <> будет хорошо работать для чисел, но будет вызывать std :: string.

Если вы пошли по шаблону маршрута, у вас теперь есть «Объект», целочисленные типы и некоторые специализации для строк, bools. Но чтобы имитировать .NET еще больше, вы, вероятно, хотите ввести интерфейсы для сравнения:

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

Это можно легко подключить к вашим классам IntegralType <> и специализациям.

Но, как заметил другой комментатор, зачем вам? boost :: any полезен, если вы пытаетесь сделать что-то вроде кортежа с именем и значением произвольного типа. Если вам нужно собрать коллекцию из них, то с вашим дизайном что-то в корне не так. Например, во всех моих программах на C # мне никогда не приходилось писать:

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

Возможно, было:

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

Но никогда ничего на уровне объектов. Зачем? Ну, кроме того, чтобы вызвать ToString () или, возможно, сделать рискованное приведение, зачем вам это нужно? Обобщения существуют в программировании, поэтому нам не нужно иметь списки объектов (или в случае C ++, void *).

Так что у вас это есть. Выше показано, как у вас могут быть объекты и целочисленные типы, вроде C #, и я пропустил множество вещей. Теперь пришло время взглянуть на ваш дизайн и решить, действительно ли это то, что вам нужно.

5 голосов
/ 26 октября 2010

Нет ничего встроенного в язык. Обычно, если вы вообще этого хотите, это означает, что ваш дизайн не очень хорошо продуман, но если вы не можете найти какой-либо альтернативы, вы можете рассмотреть (для одного примера) Boost any.

3 голосов
/ 26 октября 2010

Заголовок <comutil.h> содержит удобную оболочку для VARIANT. Заботится о правильной инициализации и очистке.

#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);

В вашем фрагменте кода нет ничего, что помогло бы мне понять, как получить указатель на интерфейс COM. Если у вас возникли проблемы, начните новый вопрос об этом.

1 голос
/ 26 октября 2010

Альтернатива для вас - взглянуть на System.Runtime.InteropServices.GCHandle, который позволяет вам находить управляемый объект из неуправляемого кода, но в любом случае вы в конечном итоге получите непристойные и рискованные приведения типов, и вам нужно очень осторожно хранить где-нибудь ссылку на управляемый объект, так как он может быть собран мусором, если в неуправляемом коде есть только ссылка.

...