Поддержать ссылку на какой-либо тип объекта в C++?

Я нашел , эта страница , чтобы быть полезным руководством в переопределении равняется - и методы типа хеша. Это включает достойный алгоритм для вычисления хэш-кодов. Страница приспособлена к Java, но довольно легко адаптировать его к Objective-C/Cocoa.

9
задан Tim 27 October 2009 в 18:35
поделиться

6 ответов

В отличие от Java, C ++ не имеет базового объекта, от которого наследуются все объекты. Обычный подход к тому, что вы хотите сделать, это использовать шаблоны . Все контейнеры в стандартной библиотеке C ++ используют этот подход.

В отличие от Java, C ++ не полагается на полиморфизм / наследование для реализации универсальных контейнеров. В Java все объекты наследуются от Object , поэтому любой класс может быть вставлен в контейнер, который принимает Object . Однако шаблоны C ++ представляют собой конструкции времени компиляции, которые инструктируют компилятор фактически сгенерировать другой класс для каждого используемого вами типа. Так, например, если у вас есть:

template <typename T>
class MyContainer { ... };

Затем вы можете создать MyContainer , который принимает объекты std :: string , и другой MyContainer, который принимает int с.

MyContainer<std::string> stringContainer;
stringContainer.insert("Blah");

MyContainer<int> intContainer;
intContainer.insert(3342);
12
ответ дан 4 December 2019 в 07:47
поделиться

Вы можете взглянуть на boost :: any class. Он безопасен по типу, вы можете поместить его в стандартные коллекции, и вам не нужно связываться с какой-либо библиотекой, класс реализован в файле заголовка.

Он позволяет вам писать такой код:

#include <list>
#include <boost/any.hpp>

typedef std::list<boost::any> collection_type;

void foo()
{
    collection_type coll;
    coll.push_back(boost::any(10));
    coll.push_back(boost::any("test"));
    coll.push_back(boost::any(1.1));
}

Полная документация здесь: http://www.boost.org/doc/libs/1_40_0/doc/html/any.html

9
ответ дан 4 December 2019 в 07:47
поделиться

Шаблоны - статический способ сделать это. Они ведут себя как дженерики Java и C #, но на 100% статичны (время компиляции). Если вам не нужно хранить разные типы объектов в одном контейнере, используйте это (другие ответы описывают это очень хорошо).

Однако, если вам нужно хранить разные типы объектов в одном контейнере, вы можете сделать это динамический способ, сохраняя указателей на базовом классе . Конечно, вы должны определить свою собственную иерархию объектов, поскольку такого класса «Object» в C ++ нет:

#include <list>

class Animal {
public:
   virtual ~Animal() {}
};

class Dog : public Animal {
public:
   virtual ~Dog() {}
};

class Cat : public Animal {
public:
   virtual ~Cat() {}
};

int main() {
    std::list<Animal*> l;
    l.push_back(new Dog);
    l.push_back(new Cat);

    for (std::list<Animal*>::iterator i = l.begin(); i!= l.end(); ++i)
        delete *i;

    l.clear();

    return 0;
}

Умный указатель проще в использовании. Пример с boost :: smart_ptr :

std::list< boost::smart_ptr<Animal> > List;
List.push_back(boost::smart_ptr<Animal>(new Dog));
List.push_back(boost::smart_ptr<Animal>(new Cat));
List.clear(); // automatically call delete on each stored pointer
2
ответ дан 4 December 2019 в 07:47
поделиться

Вы должны иметь возможность преобразовать void * в строку * , используя стандартные преобразования в стиле C. Помните, что ссылка не обрабатывается как указатель при использовании, она обрабатывается как обычный объект. Поэтому, если вы передаете значение по ссылке на функцию, вам все равно нужно отменить ссылку, чтобы получить ее адрес.

Однако, как говорили другие, лучший способ сделать это - использовать шаблоны

1
ответ дан 4 December 2019 в 07:47
поделиться
static_cast<char*>(str.c_str())

мне кажется странным. str.c_str () извлекает C-подобную строку, но с типом const char * , и для преобразования в char * вы обычно используете ] const_cast (str.c_str ()) . За исключением того, что это нехорошо, поскольку вы будете вмешиваться во внутреннее устройство строки . Вы уверены, что не получили об этом предупреждения?

У вас должна быть возможность использовать static_cast (& str) . Сообщение об ошибке, которое вы получили, подсказывает мне, что вы ошиблись в чем-то еще, поэтому, если вы могли бы опубликовать код, мы могли бы его рассмотреть. (Тип данных std :: string & является ссылкой на строку , а не указателем на нее, поэтому сообщение об ошибке правильное. Что я не делаю » я знаю, как вы получили ссылку вместо указателя.)

И да, это многословно. Так задумано. Приведение типов обычно считается неприятным запахом в программе на C ++, и Страуструп хотел, чтобы приведения было легко найти. Как обсуждалось в других ответах, правильный способ создания структуры данных произвольного базового типа - использование шаблонов, а не приведений и указателей.

1
ответ дан 4 December 2019 в 07:47
поделиться

Вы ищете шаблоны. Они позволяют создавать классы и функции, которые позволяют принимать данные любого типа.

3
ответ дан 4 December 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: