С++ специфические шаблоны из-за языкового дизайна

Мне потребовалось много времени, чтобы понять, насколько важны и тонкие переменные, которые:

1) существуют в стеке

2) вызывают их деструкторы, когда они выходят из области видимости

есть.

Эти две вещи позволяют такие вещи, как:

A) RAII

B) refcounted GC

Интересно, что (1) и (2) недоступны на "более низких" языках, таких как C/Assembly; ни на "более высоких" языках, как Ruby/Python/Java (поскольку GC предотвращает предсказуемое уничтожение объектов).

Мне интересно - какие другие методы вы знаете об этом, очень специфичны для С++ из-за выбора языка.

Спасибо!

Изменить: Если ваш ответ "это работает на С++ и этом другом langauge", это тоже хорошо. То, что я хочу узнать, похоже на:

Выбирая не иметь определенных функций (например, GC), мы получаем другие возможности (например, RAII + предикативное разрушение объектов). В каких областях С++, выбирая НЕ иметь функции, которые есть у других "более высоких уровней" langauges, С++ удается получить шаблоны, которые не могут выразить эти языковые языки более высокого уровня.

Ответ 1

Мне нравятся классные классы. Не совсем конкретный язык С++ (другие языки как Scala), но он позволяет вам адаптировать объекты, в основном, для указания набора операций, которые должен поддерживать тип. Представьте, что вы хотите "хэшировать", в смысле tr1::hash. хэш определен для некоторых типов, но не для других. Как вы можете создать класс, который имеет хэш, определенный для всех типов, которые вы хотите? Вы можете объявить класс, например:

template < typename T>
struct hashing_tratis
{
    typedef std::tr1::hash<T> hashing_type;
};

то есть вы ожидаете, что класс, который имеет правильный hasing_type, определенный для использования. Однако хэш не определен, скажем, для myType, поэтому вы можете написать:

template <>
struct hashing_traits<myType>
{
    typedef class_that_knows_how_to_hash_myType hashing_type;
};

Таким образом, предположим, что вам нужен способ хеширования любого типа, который вы используете в своей программе (включая myType). Вы можете написать "универсальный" хэш, создав свойство hasing:

template <typename T>
struct something {
    typename hashing_traits<T>::hashing_type hasher;
    .... // here hasher is defined for all your relevant types, and knows how to hash them

Ответ 3

Ну, это можно сделать на языке программирования D, а также на двух, о которых вы упоминаете, но шаблоны, достаточно мощные, чтобы по существу функционировать как компиляция времени утка набирать, очень полезны. Я часто чувствую, что значительная часть дискуссий между статическими и динамическими языками может быть решена с помощью достаточно хорошей системы шаблонов, так что даже если типы должны быть статически разрешены во время компиляции, их не нужно знать во время разработки. С++ впервые выдвинул эту идею (по крайней мере, среди основных языков). D выполняет несколько шагов далее.

С шаблонами и типичной утиной компиляции вы получаете лучшее из обоих миров: гибкость в том, что вам не нужно указывать типы во время разработки функции или класса, а также безопасность и эффективность их знания во время компиляции.

Ответ 4

  • Всегда делайте вызывающего абонента ответственным за распределение/освобождение памяти, а это означает, что код, который будет выглядеть так в Java/С#:

    MyClass doSomething(MyClass someInstance);
    

    выглядит так в C/С++:

    void doSomething(MyClass* someBuffer, MyClass* someInstance);
    
  • Использование деструкторов для закрытия сокетов, файлов и т.д.

Ответ 5

Ну, почти ВСЕ "шаблоны проектирования" имеют сильную связь с С++. Вы должны предпочесть, что у них нет НИЧЕГО делать "правильный дизайн" и "лучшие практики" и ВСЕ, что нужно делать с причудливыми недостатками С++ и тщательно учитывать реальную потребность в любом из них, а не бездумно усложнять ваш код. Тем более, что многие шаблоны проектирования являются бандаидами для устранения проблем, созданных еще другими шаблонами дизайна. Это применяется в десять раз больше, поэтому при использовании любого языка, кроме С++, потому что С++ имеет огромное количество проблем, никаких других языков.

Например, singleton является наиболее очевидным примером этого. Настоящей причиной этого является то, что С++ имеет очень слабо реализованную статическую инициализацию. Без этого вам действительно нужно знать, что вы делаете, чтобы обеспечить правильную работу инициализации, и большинство людей этого не делает. Для большинства применений дополнительные накладные расходы на однопользовательский режим прекрасны, но следует иметь в виду, что у него есть накладные расходы, и он не используется на большинстве языков. Это также создает дополнительные проблемы в каждой отдельной реализации, которую я видел.

То же самое относится к шаблону моста, я могу видеть, используя синглтоны, но просто нет причин когда-либо использовать шаблон моста. Это сводится к тому, "вы знаете, что делаете?". Если это так, вам не нужен шаблон моста. Если нет, вы должны, вероятно, узнать больше, прежде чем пытаться решить проблему, побуждая вас использовать шаблон моста. Самое главное, это не очень полезно вообще на языках, кроме С++. Дело в том, чтобы отделить реализацию и интерфейс, который в более современных языках OO уже сделан, потому что у них есть соответствующие модули. В С++ лучше использовать чистые виртуальные интерфейсы для таких случаев (и не думайте, что это имеет худшую производительность, она имеет гораздо лучшую производительность, чем шаблон моста в сочетании с шаблонами).

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

По иронии судьбы, java API полон мостов и множество других шаблонов дизайна, которые совершенно бессмысленны в Java. Java API прост в использовании большую часть времени, но сложная иерархия может быть очень громоздкой для работы.

Ответ 7

Поддержка нескольких языков множественная отправкадвойная отправка является наиболее распространенным), как это делает С++, вы можете сделать это статически или динамически.
С его помощью вы можете позволить экземплярам взаимодействовать друг с другом, не зная или не тестируя их конкретный тип.