Могу ли я переопределить функцию или проверить, существует ли она?

У меня вопрос о (пере) определяющих функциях. Моя цель – иметь скрипт, где я могу выбрать функцию или нет. Как это:

void func(){} int main(){ if (func)func(); } 

И без функции, просто:

 int main(){ if (func)func(); } 

У кого-нибудь есть идея?

Вы можете сделать это в GCC, используя расширение слабого атрибута функции:

 void func() __attribute__((weak)); // weak declaration must always be present int main() { if (func) func(); // ... } // optional definition: void func() { ... } 

Это работает, даже если func() определен в другом .c файле или в библиотеке.

Что-то вроде этого, я думаю. Не использовали указатели функций много, поэтому я, возможно, немного изменил синтаксис.

  void func() { #define FUNC_PRESENT // code } void (*funcptr)(); #ifdef FUNC_PRESENT funcptr = func; #else funcptr = NULL; #endif int main() { if (funcptr) funcptr(); } 

Используйте указатели функций, динамически устанавливайте их на основе условий выполнения и проверяйте нулевые указатели или оберните их в методы, которые проверяют вас.

Только вариант в CI может придумать.

В C ++ вы можете комбинировать шаблоны и библиотеки DLL для динамического определения во время выполнения.

На самом деле единственный способ, которым вы можете «выбрать функцию или нет», – это директивы препроцессора C. Например:

 #ifdef some_name void func() { do_whatever(); } #else //the else part is optional #endif 

Чтобы установить эти «переменные», вы используете #define some_name

Проблема в том, что все это нужно делать во время компиляции (до этого, на самом деле), поэтому это невозможно сделать с помощью оператора if подобного вашему примеру. Если вы хотите, чтобы оператор if контролировал stream вашей программы, просто используйте его и не беспокойтесь при попытке переименовать функции или с помощью указателей функций или чего-то еще.

Вступление

Я предполагаю, что вы пытаетесь это сделать:

  • Два модуля, ao и bo
  • bo содержит определение для void foo()
  • ao вызывает void foo() только в том случае, если bo также связан с окончательным исполняемым файлом.

Это может быть полезно для системы «плагин».


Вариант 1

Вы можете имитировать его с помощью указателей функций. Я не знаю достаточно C, чтобы написать это в правильном C-коде, но псевдокод выглядит так:

ах

 extern collectionOfFuncPtrs_t list; int addFuncPtr(); 

переменный ток

 #include "ah" collectionOfFuncPtrs_t list; int addFuncPtr(FuncPtr p) { - add func ptr to list - return 0 } int main() { - loop through list of function pointers - call functions through them } 

До нашей эры

 #include "ah" void bar() { /* ... */ } static int dummy = addFuncPtr(&bar); 

куб.см

 #include "ah" void ayb() { /* ... */ } static int dummy = addFuncPtr(&ayb); 

Заключение

Теперь вы можете связать в bo и / или co по своему усмотрению, и int main() будет только вызывать bar() и / или ayb() если они существуют.


Вариант 2

Поэкспериментируйте с вариантами этой темы, если она выглядит так, как будто она вам полезна. В частности, если у вас есть только определенное количество условно определенных функций, вы можете использовать кучу отдельных указателей на функции, а не какой-то список:

ах

 extern fptr_t bar_ptr, ayb_ptr; 

переменный ток

 #include "ah" int main() { if (bar_ptr) bar_ptr(); if (ayb_ptr) ayb_ptr(); } 

До нашей эры

 #include "ah" void bar() { /* ... */ } fptr_t bar_ptr = &bar; 

b_dummy.c

 #include "ah" fptr_t bar_ptr = 0; 

куб.см

 #include "ah" void ayb() { /* ... */ } fptr_t ayb_ptr = &ayb; 

c_dummy.c

 #include "ah" fptr_t ayb_ptr = 0; 

Заключение

Теперь либо ссылку bo либо b_dummy.o ; и либо ссылку co либо c_dummy.o .

Во всяком случае, я надеюсь, что ты получишь общую идею …!


Bootnote

Это намного проще на C ++, где вы можете легко писать систему регистрации модhive с помощью std::map s и конструкторов.

В C? Только используя препроцессор, как указано в других ответах.

C не является динамическим языком, например, Python.

Правильный способ сделать то, о чем я думаю, что вы спрашиваете на C, – использовать указатели на функции . Вы можете взять адрес функции, назначить ее переменной, проверить ее на нуль и т. Д. Однако простой старый C не является очень динамичным языком; вам может быть лучше использовать другой язык.

если вы не возражаете против специального расширения компилятора, вы можете использовать __if_exists :

 #include  using namespace std; // uncomment the following, and it'll still work void maybeFunc(){ cout << "running maybe" << endl; } int main(){ cout << "hi!" << endl; __if_exists(maybeFunc) cout << "maybe exists!" << endl; maybeFunc(); } } 

это работает в msvc по умолчанию и в clang, если вы используете флаг -fms-extensions .