Включение функций из заголовка с помощью define

174
28 мая 2021, 14:50

Файл a.h

#pragma once
#define _A_DEF
#include "b.h"
class A { }; // А класс

Файл b.h

#pragma once
#define _B_DEF
#ifdef _A_DEF
#define _PROV_A_DEF
#endif
class B { }; // B класс  

_A_DEF и _B_DEF "флаги" заголовков a.h и b.h, соответственно
Флаг _A_DEF сообщает b.h что нужно "включить" объявление нескольких функций, и также их определения в b.cpp (a.h содержит и объявления и определения своих функций в себе, временно, то есть у него нет a.cpp).

class B
{
#ifdef _PROV_A_DEF
friend class A; // видит класс
#endif
    ....
#ifdef _PROV_A_DEF
protected:
        void ex1(....);
        bool ex2(....);
#endif
};  

Все сделано для того, чтобы из класса А пользоваться функциями из класса В. В файле b.cpp точно также через директивы #ifdef #endif определенны функции ex1 и ex2
Однако, это все не линкуется (компилируется если не использовать в классе А "нужные" функции из класса В). Выходит ошибка: ссылка на неразрешенный символ.

Как можно провернуть все это(объявить и определить их в зависимости от наличия флага из файла a.h)?

P.S.
Макрос _PROV_A_DEF определен дополнительно и возможно излишне, так как с _A_DEF не получалось(решил что b.cpp не видит _A_DEF, а b.h видит).
Также, "отключение" pragma once в b.h не решает проблему

Пример желаемой работы:
b.h

#pragma once
#include <iostream>
#include <vector>
#define _B_DEF
#ifdef _A_DEF
#define _PROV_A_DEF
#endif
class B
{
#ifdef _PROV_A_DEF
friend class A; // видит класс
#endif
    B () {}
    void ex1(::std::vector<int>);
    bool ex2(int);
#ifdef _PROV_A_DEF
protected:
    void ex1(::std::vector<int>, int);
    bool ex2(int, int);
#endif
}; 

b.cpp

#include "b.h"
void B::ex1(::std::vector<int> vint)
{
    ::std::cout << vint.size() << ::std::endl;
}
bool B::ex2(int x)
{
    return x == 12;
}
#ifdef _PROV_A_DEF
void B::ex1(::std::vector<int> vint, int x)
{
    ::std::cout << vint.size() + x << ::std::endl;
}
bool B::ex2(int x, int num)
{
    return x == num;
}
#endif

a.h

#pragma once
#include <vector>
#define _A_DEF
#include "b.h"
class A
{
public:
    B test;
    A () {}
private:
    void somefunc()
    {
        test.ex1(::vector<int>{1, 2, 3}, 4); // вызов перегруженной функции
        bool res = test.ex2(4, 4);           // вызов перегруженной функции
    }
};

В main.cpp

#include "a.h" // подключен b.h с доп. функциями
int main()
{
    A testa;
    testa.somefunc();
    return 0;
}

Если бы я не хотел добавлять в проект "надстройку", то main выглядел бы так

#include "b.h" // подключен b.h без доп. функций
int main()
{
    ...
    return 0;
}
Answer 1

Решил проблему следующим образом.
Так как проблема была именно в линковке b.cpp(файл b.cpp не видел макросов), я перетащил определения "дополнительных" функций в a.h(временно там находятся и объявления и определения, то есть с a.cpp не пробовал).
Все остальное осталось на своих местах, флаги файлов a.h и b.h в самих заголовках, а объявления "дополнительных" функций в b.h так же остались завернуты в #ifdef и #endif.

READ ALSO
Убрать checked с потомков input[type=checkbox]

Убрать checked с потомков input[type=checkbox]

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

348
Как сверстать круговую диаграмму с фоновым изображением?

Как сверстать круговую диаграмму с фоновым изображением?

Внимание! Это дубль вопроса с тостера! Автор не я, просто вопрос показался интересным:

91
Вставка даты по умолчанию на HTML странице

Вставка даты по умолчанию на HTML странице

Для выгрузки операций из БД на html-странице есть 2 окна для ввода периода времени "с" и "по"Если написать в коде страницы: body onload = "ShowMonthDate();", то при...

145
Сетка товаров на Grid

Сетка товаров на Grid

У меня есть сетка товаров сделанная на гридахКоличество товаров в ряду - 4, рядов может неопределенное количество

106