0

So, if i have 3 headers like this

headers.h

#pragma once

#include <string>

#define FRAMEWORK_API extern "C" __declspec(dllimport)

class Sprite;

FRAMEWORK_API Sprite* createSprite(const char* path);

Event.h

#pragma once

#include "headers.h"

class Event
{
public:
    int spriteInit(std::string path = ".\\data\\Player\\TankPlayer*.png");
};

Event.cpp

int Event::spriteInit(std::string path)
{
    Sprite* newSpirte = createSprite(path);
}

Manager.h - Not deriving from Event, but includes

#pragma once

#include "Event.h"

class Manager
{
        /// Send event to all interested Objects.
        /// Return count of number of events sent.
        int onEvent(const Event *ptrEvent) const;
};

So, the question is, how to make Manager.h, not to see #include "headers.h", from Event.h?

I don't want Manager.h to see string and methods of the FRAMEWORK_API

UPDATE 1: I have changed names of Classes to make sense, why do i want to do this

UPDATE 2: I making it, because I can't #define FRAMEWORK_API extern "C" __declspec(dllimport) twice in the code

  • 1
    You don't. Why is it in "ClassA.h" in the first place? – molbdnilo Mar 10 '21 at 12:00
  • Because I have a Framework, that includes his methods which is defined with ```#define FRAMEWORK_API extern "C" __declspec(dllimport)``` – Windings-Lab Mar 10 '21 at 12:01
  • if you only include what you need to include then there is no issue. Either `ClassA.h` needs to include `headers.h` or it does not. If it does, then `ClassB.h` needs it as well – 463035818_is_not_an_ai Mar 10 '21 at 12:02
  • Relevant: [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/q/625799/10147399) – Aykhan Hagverdili Mar 10 '21 at 12:15
  • 1
    Best practice is to only inculde the bare minimum of what you need. This will have various benefits, like fewer dependencies and thus an enhanced software structure, easier to write tests, faster compile times,... . If you then remove some includes it won't compile anymore. – schorsch312 Mar 10 '21 at 12:16
  • @schorsch312 ```Event.h``` need ```headers.h``` because I can't ```#define FRAMEWORK_API extern "C" __declspec(dllimport)``` twice in the code – Windings-Lab Mar 10 '21 at 12:18
  • @AntonZhukov Then you need to guard the define like the old header guard style. #ifndef FRAMEWORK_API #define FRAMEWORK_API extern "C" __declspec(dllimport) #endif – schorsch312 Mar 10 '21 at 12:34
  • You have your `#pragma once` which avoid to include twice (in same TU) headers.h – Jarod42 Mar 10 '21 at 13:01
  • For `#define`, you might still guard then BTW: `#ifndef MACRO #define MACRO /*..*/ #endif`. – Jarod42 Mar 10 '21 at 13:02
  • Are C++20 modules an option? – Jarod42 Mar 10 '21 at 13:04
  • @Jarod42 Yes, I think? I don't know about this – Windings-Lab Mar 10 '21 at 13:43
  • [C++20 modules](https://en.cppreference.com/w/cpp/language/modules) are recent and requires to adapt the build chain. modules allow to be more selective on what is exported, so module "event.h" might include or import "hearder.h" but only **export** `class Event`. so importing module "event.h" would only import `class Event`. – Jarod42 Mar 10 '21 at 13:50

1 Answers1

3

So, the question is, how to make ClassB.h, not to see #include "headers.h", from ClassA.h?

By not including headers.h into ClassA.h. Or by not including ClassA.h into ClassB.h.

In other words, you must give up on one of the premises, or your desire goal. They are in contradiction.

If ClassA.h depends on declarations in headers.h1, and ClassB.h depends on declarations in ClassA.h2, then ClassB.h transitively depends on declarations in headers.h. If one of the assumptions 1 or 2 do not hold, then simply remove the unused include. If they hold, then you cannot avoid including definitions that you depend on. One thing that you may try is to get rid of one of the dependencies.


Regarding the edited question

#include "Event.h"

class Manager
{
        /// Send event to all interested Objects.
        /// Return count of number of events sent.
        int onEvent(const Event *ptrEvent) const;
};

The class Manager does not depend on the definition of the class Event. Therefore it doesn't need to include its definition. Manager only depends on the declaration of Event. Define a separate header that only has that definition.

Furthermore, your Event.h does not depend on headers.h. The problem is solved by simply removing the unused include.

// EventFwd.hpp
class Event;


// Event.hpp
#pragma once
#include "EventFwd.hpp"
// do not include "headers.h"
class Event
{
};


// Manager.hpp
#pragma once
#include "EventFwd.hpp"
// do not include "Event.hpp"
class Manager
{
    int onEvent(const Event *ptrEvent) const;
};
eerorika
  • 232,697
  • 12
  • 197
  • 326