Вопрос:
возможно ли иметь 2 (или более) разных реализации для той же функции, объявленной в файле заголовка?
Я приведу пример – скажем, у нас есть заголовочный файл с именем common.h и 2 исходными файлами с именем src1.c и src2.c.
Содержание
common.h
//lots of common function declarations implemented in some file common.c int func(int a, int b);
src1.c
#include «common.h» int func(int a, int b) { return a+b; }
src2.c
#include «common.h» int func(int a, int b) { return a*b; }
скажем, что я хочу, чтобы каждый из исходных файлов использовал свою локальную версию func(). можно ли это сделать?
Лучший ответ:
Если вы хотите, чтобы каждый исходный файл только использовал свою локальную реализацию func, и ни один другой модуль не использовал эти функции, вы можете удалить объявление из заголовка и объявить их как static.
src1.cstatic int func(int a, int b) { return a+b; } src2.cstatic int func(int a, int b) { return a*b; }
Таким образом, каждая из этих функций видна только в модуле, в котором он определен.
EDIT:
Если вам нужны две или более функции для реализации интерфейса, вам нужно дать им разные имена, но вы можете использовать указатель на функцию, чтобы выбрать тот, который вы хотите.
common.htypedef int (*ftype)(int, int); int func_add(int a, int b); int func_mult(int a, int b); src1.c#include «common.h» int func_add(int a, int b) { return a+b; } src2.c#include «common.h» int func_mult(int a, int b) { return a*b; }
Затем вы можете выбрать один или другой:
ftype func; if (op==’+’) { func = func_add; } else if (op==’*’) { func = func_mult; … } int result = func(value1,value2); Ответ №1
Да, но если вы попытались связать свою основную программу с обоими src1 и src2, вы столкнулись бы с ошибкой, потому что не знали, какое определение использовать.
Заголовки – это просто способы для других объектов кода знать о том, что доступно в других объектах. Думайте о заголовках как о контракте. Ожидается, что контракты будут заполняться ровно один раз, а не ноль или несколько раз. Если вы ссылаетесь как на src1, так и на src2, вы существенно заполнили контракт int func(int a, int b); дважды.
Если вам нужно чередовать две функции с одной и той же сигнатурой, вы можете использовать указатели функций.
Ответ №2
Если вы скомпилируете его с каждым src [x].c, вы сможете использовать его в любой функции вашего .c
Ответ №3
Вы можете решить не подвергать реализацию функции другим единицам перевода. В c используйте ключевое слово static перед сигнатурой функции, где вы реализуете функцию (см. Код ниже); В С++ вы также можете использовать неназванные пространства имен. Таким образом, компоновщик не даст вам ошибки, и каждая единица перевода будет использовать ее собственную реализацию:
Предположим, что следующие две единицы перевода main.c и another.c. Оба имеют свою (закрытую) реализацию int function(a,b), так что при вызове он дает разные результаты:
extern void someOtherFeature(); static int function (a,b) { return a+b; } int main(){ int x = function(1,2); printf(«main: function(1,2)=%dn», x); someOtherFeature(); } // another.c: #include <stdio.h> static int function (a,b) { return a*b; } void someOtherFeature() { int x = function(1,2); printf(«someOtherFeature: function(1,2)=%dn», x); }
Вывод:
main: function(1,2)=3 someOtherFeature: function(1,2)=2
Однако, если обе единицы перевода разоблачили свои реализации (т.е. оба опущены ключевое слово static, то компоновщик сообщит об ошибке, например duplicate symbol _function in:….
Ответ №4
Если вы хотите, чтобы каждый исходный файл использовал локальную версию func, просто поместите его в неназванное пространство имен:
Например src1.C:
namespace { int func(int a, int b) { return a+b; } }
Затем каждый исходный файл будет использовать свою собственную версию. Вам не нужно объявлять его в заголовке.
Обратите внимание, что ваш исходный код с определениями в глобальном пространстве имен и объявлен в заголовке, нарушает одно правило определения (два определения функций для одного и того же имени всегда должны иметь одинаковое определение), вызывая поведение undefined, не требуя диагностики.