Определенный пользователем оператор преобразования в качестве аргумента для printf

StackOverflow https://stackoverflow.com/questions/2486713

Вопрос

У меня есть класс, который определяет определяемый пользователем оператор для TCHAR*, например:

CMyClass::operator const TCHAR*() const
{
    // returns text as const TCHAR*
}

Я хочу иметь возможность сделать что-то вроде

CMyClass myClass;
_tprintf(_T("%s"), myClass);

или даже

_tprintf(_T("%s"), CMyClass(value));

Но при попытке printf всегда печатает (null) вместо значения.Я также пробовал обычный оператор char*, а также варианты с const и т. д.Это работает правильно, только если я явно вызываю оператор или выполняю приведение, например

_tprintf(_T("%s\n"), (const TCHAR*)myClass);
_tprintf(_T("%s\n"), myClass.operator const TCHAR *());

Однако я не хочу кастовать.Как этого можно достичь?

Обратите внимание, что есть возможность создать функцию с параметром const TCHAR*, чтобы она принудительно вызывала оператор TCHAR*, но я тоже не хочу это реализовывать.

Это было полезно?

Решение

Избегайте операторов преобразования.Они редко делают то, что вы хотите, и тогда явные призывы болезненны.Переименовать operator const TCHAR*() const к TCHAR *str() const.

Другие советы

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

Операторы преобразования вызываются, когда компилятор хочет преобразовать значение в другой тип.Это работает для функций, которые принимают определенные параметры определенных типов.Это не работает для переменных функций, таких как printf() с ... в объявлении функции.Эти функции принимают аргументы и затем работают с ними, поэтому оператор преобразования никогда не вызывается.

Точнее, когда компилятор видит printf("%s", foo), оно проходит foo, что бы это ни было, чтобы printf(), который должен будет предположить, что он подходит для %s формат как есть.Оператор преобразования вызываться не будет (хотя определенные арифметические действия будут иметь место).

Операторы преобразования обычно вызывают проблемы.Имея этот оператор в этом классе, вы усложняете разрешение перегрузки функции, поскольку компилятор может интерпретировать CMyClass как если бы это было TCHAR *.Это может привести к неожиданным результатам: либо вызвать компиляцию кода, когда вы этого действительно не хотите, либо выбрать неправильную перегруженную функцию.(Например, учитывая CMyClass cmc;, выражение cmc + 10 внезапно становится законным, поскольку TCHAR * + int является совершенно законной арифметикой указателей.) Обычно такие преобразования обозначаются как explicit.

Приведение — это правильно, если вы хотите использовать API-интерфейсы в стиле printf и полагаться на оператор преобразования (и я не собираюсь здесь спорить, следует ли вам использовать эти функции).Однако я бы использовал статическое приведение, например. _tprintf(_T("%s\n"), static_cast<const TCHAR*>(myClass));

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top