LINUX.ORG.RU

[c++]Выбор *.h при компиляции

 


0

0

Не знаю как лучше реализовать. Есть три файла h1.h, h2.h и main.cpp. В зависимости от типа задачи нужно подключить один из хедеров и вызвать из нее функцию, у которой аргументы как и в другом *.h файле.

main.cpp

int main()
{
    int a=5;
    f(a);
    return 0;
}

h1.h

void f(int a){printf("%i\n",a);}

h2.h

void f(int a){printf("%i\n",a+1);}

Если сделать одинаковые функции, с одинаковыми аргументами компилятор ругается, что функция переопределена.

★★★★★

#ifdef

дай функциям человеческие имена «В зависимости от типа задачи» и проблема сама пропаддёт.

golodranez ★★★★
()

Лучше реализовывать в *.c файлах, но всё же...

попробуйте в main.c

#define __MAIN_C
int main()
{
int a=5;
f(a);
return 0;
}
#endif


ну и в хеадерах:

1:
#ifdef __MAIN_C
void f(int a){printf(«%i\n»,a);}
#endif


2:
#ifdef __MAIN_C

#else
void f(int a){printf(«%i\n»,a+1);}
#endif

velikS
()
Ответ на: комментарий от golodranez

дай функциям человеческие имена «В зависимости от типа задачи» и проблема сама пропаддёт.

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

З.ы. Названия файлов привел так лишь для простоты.

Zodd ★★★★★
() автор топика

Всем спасибо. Что-то при сборке произошел какой-то сбой. #ifdef - заработал.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

...виртуальные функции.

Вот это наверное надо попробовать. // Благо у меня функции реализованы через класс.

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Zodd

>...виртуальные функции.

Вот это наверное надо попробовать.

для статической (compile-time) настройки функциональности ты собираешься использовать позднее связывание (run-time)?

jtootf ★★★★★
()
Ответ на: комментарий от Zodd

Да как вам угодно! Я подкинул идею, а реализация - ваше дело, я ж не знаю, что ещё в этом файле у вас находится.

Ключевое слово: препроцессор

velikS
()
Ответ на: комментарий от jtootf

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

solve.cpp

void solve(int a, ...) // хочу сделать в виде библиотеки
{
    .... // этот код не меняется
    f(int a); // меняется для разных задач
    ....
}

main.cpp

#define H1

#ifdef H1
#include "h1.h"
#endif

#ifdef H2
#include "h2.h"
#endif

int main()
{
   int a;
   solve(a,...);
   return 0;
}

Zodd ★★★★★
() автор топика
Ответ на: комментарий от jtootf

чему учат отцы вроде Саттера? они учат выбору функций через параметры шаблонов со связыванием в процессе компиляции.

anonymous
()
Ответ на: комментарий от anonymous

чему учат отцы вроде Саттера? они учат выбору функций через параметры шаблонов со связыванием в процессе компиляции.

Есть ещё вариант boost::function, если, конечно, дополнительные накладные расходы не будут слишком уж большими.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

И когда же люди узнают про указатели на функции и функциональные объекты!?

Я не совсем понимаю как и где это работает. Можно объяснить на пальцах или показать на моем примере как это делается?

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Zodd
void solve(void (*f)(int), int a, ...) // хочу сделать в виде библиотеки 
{ 
    .... // этот код не меняется 
    f(); // меняется для разных задач 
    .... 
} 

...

solve(f1, a1, ...);
solve(f2, a2, ...);
Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Вот теперь въехал как это работает. Спасибо.

Еще один вопрос: а как в случае для функции с многими переменными f(a,b,c,d,e,f)?

Так? void solve(void (*f)(int,int,int,int,int), int a, ...)

Zodd ★★★★★
() автор топика
Ответ на: комментарий от Begemoth

В догонку замечание по стилю: лучше объявлять типы этих функций:

typedef void (*f)(int,int,int,int,int) FFunction;

void solve(FFunction f, int a,...);
Begemoth ★★★★★
()
Ответ на: комментарий от Zodd

Вариантов решения огромное кол-во.

Lib.h

extern int (*f1)(int);
extern int (*f2)(int);
extern int (*f3)(int);
extern int (*f4)(int);

void SetLib(int p);
Lib.c
int (*f1)(int);
int (*f2)(int);
int (*f3)(int);
int (*f4)(int);

int a(int)
{
	return 1;
}
int b(int)
{
	return 2;
}

void SetLib(int p)
{
	switch(p)
	{
	case 1: f1 = a; // f2 = и так далее
	case 2: f1 = b; // f2 = и так далее
	}
}

Закидывая все указатели на функции в структуру, можно обойтись одним глобальным объектом и функциями-посредниками.

anonymous
()
Ответ на: комментарий от jtootf

Полиморфи́зм — взаимозаменяемость объектов с одинаковым интерфейсом

Это как раз то что тебе нужно, если я правильно понял. Ты просто на плюсах пытаешься писать в процедурном стиле. Тебе нужно менять реализацию на ходу. В ООП оно делается с помощью этого самого полиморфизма.

Например.

// Определяешь интерфейс:
interface Foo
{
    void f(int a);
}

// Потом два объекта которые реализуют этот интерфейс по разному.

class FooImplementation1 implements Foo
{
    public void f(int a)
    {
        // ...
    }
}

class FooImplementation2 implements Foo
{
    public void f(int a)
    {
        // ...
    }
}

// И в коде используешь примерно так:
Foo foo;

// А тут в зависимости от какого-то условия foo будет ссылаться 
// уже на конкретную реализацию (объект).
if (...)
    foo = new FooImplementation1();
else
    foo = new FooImplementation2();

foo.f(1);
Как-то так. В простейшем случае. Считай это псевдокодом, я пока еще к реализации ООП в С++ не дошел.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

А чем плох процедурный стиль? зачем нагромождения геморроя из классов и интерфейсов? зачем вместо sin(x) писать foo.sin(x)?

anonymous
()
Ответ на: комментарий от urxvt

Ой, пардон. Я тебя с топикстартером перепутал.

мило. я уж подумал, что это такой тонкий троллинг :)

jtootf ★★★★★
()
Ответ на: комментарий от anonymous

Присоединяюсь к вопросу? Какой от него профит?

Zodd ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Ну как сказать... извечно войны идут Procedural programming VS OOP.
Есть мнение что с помощью OOP проще писать большие и гибкие приложения.

urxvt ★★★★★
()
Ответ на: комментарий от anonymous

>А чем плох процедурный стиль? зачем нагромождения геморроя из классов и интерфейсов? зачем вместо sin(x) писать foo.sin(x)?

В некоторых случаях ООП более удобно для работы, например в ORM. Работать с объектами гораздо приятнее, чем городить кучу sql запросов. Просто ООП надо в меру использовать, а не «мы сделаем всё через классы».

А интерфейсы не нужны, лишний код и всё тут.

anonymous
()
Ответ на: комментарий от urxvt

Есть мнение

есть мнение, что коровы летают. утверждения в технических обсуждениях принято аргументировать

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> утверждения в технических обсуждениях принято аргументировать
Данная аргументация немедленно перерастет в холивар. Это все равно что аргументировать почему Имакс лучше Вима.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

в холивар как раз перерастают неаргументированные высказывания, которые невозможно обсуждать объективно. вроде твоих

jtootf ★★★★★
()
Ответ на: комментарий от urxvt

> Я тебя с топикстартером перепутал.

Тред-заставил-плакать-2. )))

LamerOk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.