На ваш вопрос:
- Обычно лучше избегать неявного преобразования. Кроме того, вы не сможете повторно использовать
std::string
операторов, таких как +, + =, с таким подходом, не добавляя многострочную функцию. Класс-обертка не принесет вам ничего, кроме добавления дополнительных преобразований, так как вы будете использовать новый тип строки, а при использовании подхода mixin это даже хуже, так как вам также нужно преобразовывать собственные типы.
- Зачем вам использовать виртуальное наследование? Вы действительно хотите получить из нескольких классов, которые имеют общую базу и имеют свои собственные данные.
- Поскольку это плохой дизайн, вы, вероятно, не найдете много людей, делающих это. Ваша конструкция увеличивает сцепление, приводит к увеличению класса, увеличению числа типов преобразований и усложняет техническое обслуживание.
- Полагаю, такой вещи не существует.
Для простых функций, подобных описанным выше, предпочтительным подходом было бы определение пространства имен (или многих, если у вас много функций, которые можно каким-то образом классифицировать, например, манипулирование именами файлов), а затем иметь свободные функции внутри него.
Используя пространство имен, вы получаете несколько преимуществ:
- Если вы вызываете много функций, вы всегда можете добавить оператор использования внутри вашей функции или исходного файла (никогда в заголовочном файле).
- Автоматическое предложение будет хорошо работать, чтобы найти эти функции.
Если некоторые из оригинальных миксинов поддерживают состояние, то вам следует сделать вспомогательный класс. Это может иметь место для такого класса, как конструктор HTML, в котором могут быть такие функции, как AddTag, Add Attribute, AddEncodedUrl и т. Д., Которые можно использовать для создания документа HTML.
Одним большим преимуществом этого подхода является то, что сцепление намного слабее, чем в вашей конструкции. Например, файловая пара (заголовок и источник) будет содержать все функции, используемые для принтера. Если вам это нужно, вам не нужно создавать новый класс, который использует какую-то комбинацию mixin.
Одна большая проблема с вашим подходом состоит в том, что со временем у вас будет много разных StringType<…>
Если у вас есть 5 миксинов, которые можно использовать, у вас есть 2 ^ 5 = 32 класса. В этот момент почти наверняка вам понадобится миксин, который вы не включили, и тогда у вас будет каскадное изменение, если вызов будет глубоким. И если вы будете использовать шаблон повсеместно, у вас будет замедление компиляции и, возможно, некоторый раздувшийся код.
Большинство экспертов считают, что неявное преобразование лучше всего избегать. Если у вас есть многократное преобразование из и во многие классы, в какой-то момент у вас будут неожиданные преобразования или двусмысленности. Явное преобразование может ограничить проблему. Обычно лучше всего использовать явное преобразование, как это было сделано экспертами в std::string
. Вы должны вызвать функцию-член c_str()
, если хотите получить строку в стиле C.
Например, поскольку ваш класс StringType
определяет преобразование в const char *
и QString
, то, если у вас есть метод, который принимает оба (возможно, функцию Append), тогда у вас конфликт.
Если вы действительно хотите преобразование, используйте вместо этого именованный метод (например, AsQString()
, c_str()
, tostdstring()
...). Это помогает гарантировать, что все преобразования предназначены. Это облегчает их поиск, и, конечно, лучше использовать явное приведение, как вы сделали в нескольких местах в вашем коде. Хотя static_cast
и другие приведения иногда полезны, они также могут скрывать некоторые проблемы, когда код подвергается рефакторингу, как в некоторых случаях, приведение может скомпилироваться, хотя оно и не является правильным. Это будет иметь место, если вы приведете к производному классу и в какой-то момент решите заменить производный класс на что-то другое и забудете обновить некоторые приведения.
Вы должны выбрать наиболее подходящую строку для вашего приложения и выполнить преобразование при необходимости.В больших приложениях вы можете использовать один тип для пользовательского интерфейса (например, CString или QString) при использовании стандартной строки в библиотеках, которые совместно используются платформами или сторонней библиотекой.Некоторое время у этих библиотек есть свой собственный класс строк.Ваш выбор должен попытаться минимизировать бесполезные конверсии.