Пользовательский оператор преобразования в качестве аргумента для printf - PullRequest
3 голосов
/ 21 марта 2010

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

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

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

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

или даже

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

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

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

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

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

Ответы [ 4 ]

9 голосов
/ 21 марта 2010

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

2 голосов
/ 21 марта 2010

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

1 голос
/ 22 марта 2010

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

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

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

0 голосов
/ 14 августа 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...