3

Base class is not able to view the macros defined in the derived class on the creation of derived class object. [C++14]

Base.HPP

class Base {
public:
    Base() {
        #ifndef SKIP
        std::cout << "Bing" << std::endl;
        #endif
    }
};

File : Derived.HPP

#define SKIP
class Derived : public Base {
public:
    Derived() {}
};

So, whenever I create the object of Derived class I expected not to see the Bing in the output terminal since I have defined the macro SKIP.

But this does not happens. It seems Base class is clueless about the definition of macro SKIP. Is there a way to do it or this is not possible to do it without compiling the code with -DSKIP flag?

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
letsBeePolite
  • 2,183
  • 1
  • 22
  • 37
  • Don't use macros? – Barry Feb 27 '17 at 19:09
  • include files are typically processed only once, so if SKIP isn't defined at the point it is processed, then "Bing" won't appear. – Steve Lorimer Feb 27 '17 at 19:10
  • Macros do text replacement before the compiler gets to see the code. If you make a [mcve] people might be able to help you, right now we can't even tell if you `#define`d `SKIP` before or after `#include`ing *Base.HPP* which is important. Also you are probably violating the [ODR](https://stackoverflow.com/questions/4192170) and are on the way to [UB](https://stackoverflow.com/documentation/c%2b%2b/1812/undefined-behavior#t=201702271913219429673). – nwp Feb 27 '17 at 19:11

2 Answers2

7

First, don't use macros.

Second, SKIP will be checked for defined-ness at the time that the class declaration of Base is processed - not when the class declaration of Derived is processed, so if you #define it where you are, it's just too late. You need to do it way earlier:

#define SKIP
#include "Base.hpp"

class Derived : public Base { ... };

But make sure you define or don't define SKIP the same way before every inclusion of Base, or it's an ODR-violation. Or simply define it on the command line.

But, really, don't use macros. Pass a bool.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • And if you really, really, really have to use a macro, make it a long and ugly name so it won't clash with anything else out there, e. g. "SKIP_COUT_IN_THIS_CLASS_OF_MY_SUPER_COOL_LIBRARY" ;-) – zett42 Feb 27 '17 at 21:15
1

You can use templates instead of macros :

template<bool skip>
struct Base {};

template<>
struct Base<false> {
    Base() {
        std::cout << "Bing" << std::endl;
    }
};

Then, when creating your Derived class, you do this:

struct Derived : Base<true> {};

If you put true as the template parameter, it will select the other base class that output Bing.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • To the downvoter: what is wrong with my answer? I'm trying to show another way OP can achieve what he want. Is there a way I can improve my answer? – Guillaume Racicot Feb 27 '17 at 19:49