Программирование на интерфейсе означает соблюдение «контракта», созданного с использованием этого интерфейса. И поэтому, если ваш интерфейс IPoweredByMotor
имеет метод start()
, будущие классы, которые реализуют интерфейс, будь то MotorizedWheelChair
, Automobile
или SmoothieMaker
, при реализации методов этого интерфейса добавят гибкости вашей системе потому что один кусок кода может запустить двигатель множества различных типов вещей, потому что все, что нужно знать одному коду, - это то, что они отвечают start()
. Неважно , как они начинают, просто они должны начинать .
Это плохая идея , потому что абстракция va_list предназначена для того, чтобы скрыть некоторые мрачные детали компилятора / архитектуры, касающиеся указателей стека и тому подобного. И после инициализации он в значительной степени привязан к области видимости функции. Если вы развернете стек и ссылаетесь на предыдущие кадры va_args вне области видимости, все может пойти плохо. Вы можете передавать их, но ...
ожидайте ошибок
См .: http://lists.freebsd.org/pipermail/freebsd-amd64/2004-August/001946.html
Также проверьте man (3) va_copy и друзья для более безопасной обработки va_args и их передачи.
IMHO, материал va_args не очень изящный. В прошлом я имел дело с этим, инициализируя структуры / непрозрачные указатели в куче, а затем используя арифметику указателей для обработки данных.
Я понимаю и согласен с предупреждениями Эйдена - va_list
и друзья опасны, так как они скрывают низкоуровневые соглашения о вызовах. Но ... в этой ситуации, я думаю, у тебя нет другого выхода. Поместите статический ...
функцию в файл .c
, чтобы никто другой не мог ее увидеть, своего рода прокси для функции, которую вам нужно вызвать, черт возьми, проверьте это и готово. Только убедитесь, что вы не выставляете вариативные аргументы вверх по цепочке вызовов.
Ваше представление о функции прокси, которая создает va_list
, является правильным способом сделать это. Нет необходимости, чтобы этот прокси имел общедоступную область действия. Однако, если вы можете обнаружить, что прокси уже существует. Например, во многих реализациях библиотеки sprintf ()
является просто прокси для vsprintf ()
.
Если вы не хотите привязать свой код к конкретному компилятору и целевой платформе, нет лучшего способа. Имена, определенные в
, предназначены для обеспечения переносимого и согласованного интерфейса для поддержки доступа к спискам переменных с переменным числом аргументов. Единственный переносимый способ реализовать и использовать вариативные функции - через этот интерфейс.
Тем не менее, возможно, вы пожертвуете переносимостью, продублировав кадр вызова в массиве и вручную построив va_list
, который правильно ссылается на него. Результат никогда не будет портативным.