Я пытаюсь написать метод, который принимает класс, полученный из std :: string в качестве аргумента. Метод перегружен несколькими сигнатурами функций. Я бы хотел, чтобы компиляция не удалась, если я попытаюсь вызвать ее с помощью std :: string или, по крайней мере, из-за ошибки времени выполнения, но, видимо, компилятор слишком умен для меня.
class NotAString : public std::string {
NotAString(std::string str) : std::string(str) { }
};class Foo {
Foo();
void bar(NotAString);
void bar(int)
};
Это компилирует и запускает
Foo foo();
foo.bar(NotAString("baz"));
Но это так:
Foo foo();
foo.bar(std::string("baz"));
Я пробовал использовать typeid (str) так:
void Foo::Bar(NotAString str) {
if(typeid(&str) != typeid(new NotAString()) {
throw std::bad_typeid();
}
}
Но он всегда выдает исключение, если передается ему std :: string или NotAString. Я попытался использовать dynamic_cast так:
void Foo::Bar(NotAString str) {
if (dynamic_cast<NotAString*>(&str) == NULL) {
throw std::bad_type();
}
}
Но это никогда не бросает исключения.
Цель состоит в том, чтобы иметь возможность различать строку и строку, которая представляет ключ для поиска значения ключа. Как я могу изменить свой класс NotAString или применить более строгую проверку типов компилятором, чтобы заставить это работать так, как мне бы хотелось?
Проблема ваша NotAString(std::string str)
конструктор не explicit
так что это позволяет неявные преобразования из std::string
в NotAString
,
Когда вы вызываете функцию с std::string
компилятор замечает, что вы можете вызвать его путем преобразования аргумента через конструктор, поэтому он создает NotAString
временно и передает его в функцию.
Если вы объявите это explicit NotAString(std::string str)
тогда это не позволит эти неявные преобразования.
Ваши попытки проверить тип внутри функция никогда не будет работать, к этому моменту компилятор должен создать NotAString
и все, что вы тестируете, является ли NotAString
аргумент не является NotAString
… который, очевидно, не будет работать.
Оставьте в стороне плохие дизайнерские идеи, замените этот конструктор …
class NotAString : public std::string {
NotAString(std::string str) : std::string(str) { }
};
…быть explicit
:
class NotAString : public std::string {
explicit NotAString(std::string str) : std::string(str) { }
};
Что помешает std::string
объекты из неявно преобразуются в NotAString
когда они используются в качестве параметра функции.