В C ++ есть особенность (я не могу определить ее правильное имя), которая автоматически вызывает соответствующие конструкторы типов параметров, если типы аргументов не являются ожидаемыми.
Очень простой пример этого вызова функции, ожидающей std::string
с const char*
аргументом. Компилятор автоматически сгенерирует код для вызова соответствующего std::string
конструктора.
Мне интересно, это так плохо для читабельности, как я думаю, что это?
Вот пример:
class Texture {
public:
Texture(const std::string& imageFile);
};
class Renderer {
public:
void Draw(const Texture& texture);
};
Renderer renderer;
std::string path = "foo.png";
renderer.Draw(path);
Это просто нормально? Или это заходит слишком далеко? Если я не должен этого делать, могу ли я заставить Clang или GCC предупредить об этом?
Ответы:
Это называется конвертирующим конструктором (или иногда неявным конструктором или неявным преобразованием).
Я не знаю переключателя времени компиляции, чтобы предупредить, когда это происходит, но это очень легко предотвратить; просто используйте
explicit
ключевое слово.Относительно того, является ли преобразование конструкторов хорошей идеей: это зависит.
Обстоятельства, при которых неявное преобразование имеет смысл:
std::string
отражают ту же концепцию, из которойconst char *
он может неявно конвертировать), поэтому неявное преобразование имеет смысл.Обстоятельства, при которых неявное преобразование имеет меньше смысла:
AnsiString
класс не должен неявно конструироваться из aUnicodeString
, поскольку преобразование Unicode-в-ANSI может потерять информацию.Дальнейшее чтение:
источник
Это скорее комментарий, чем ответ, но слишком большой, чтобы его можно было добавить в комментарий.
Интересно,
g++
что не позволяет мне это сделатьПроизводит следующее:
Однако, если я изменю строку на:
Он выполнит это преобразование.
источник
gcc
компилятора (которые, похоже, не существуют для решения этого конкретного случая). Я не стал вдаваться в подробности (я должен работать :-), но с учетомgcc
соблюдения стандарта и использованияexplicit
ключевого слова опция компилятора, вероятно, была сочтена ненужной.Texture
с другом , и, вероятно, не следует создавать их неявно (в соответствии с рекомендациями в других ответах), так что лучше будет сайт вызоваrenderer.Draw(Texture("foo.png"));
(при условии, что он работает так, как я ожидал).Это называется неявным преобразованием типов. В целом это хорошо, так как препятствует ненужному повторению. Например, вы автоматически получаете
std::string
версиюDraw
без необходимости писать для нее дополнительный код. Это также может помочь в следовании принципу открытого-закрытого, поскольку позволяет расширятьRenderer
возможности без измененияRenderer
самого себя.С другой стороны, это не лишено недостатков. С одной стороны, это может затруднить выяснение источника аргументов. Иногда это может привести к неожиданным результатам в других случаях. Вот для чего
explicit
ключевое слово. Если вы поместите его вTexture
конструктор, он отключит использование этого конструктора для неявного преобразования типов. Мне не известен метод глобального предупреждения о неявном преобразовании типов, но это не значит, что метод не существует, только то, что у gcc есть непостижимо большое количество опций.источник