简体   繁体   中英

Using preprocessor #ifdef on a class field

This class was defined in my project:

class B : public A
{
 public:
 A& Get_a(int type);

 ...
 protected:
 #ifdef COMPILE_FLAG
 int line_num;
 const char* file_name;
 #endif
 ...
 private:
 int int_value;
 bool bool-val;
};

The function Get_a is implemented like this (I put the relevant parts only):

A& B::Get_a(int type)
    {
     B* returned_a = B->Get_val(type);
     return *(A*)(returned_a) ;
    }

This is the code where I use this class:

{
...
B b_val;
A* a_val = &b_val->Get_a(5);
...
}

My code is compiled to a different DLL than the DLL where the classes A and B are compiled to. My DLL doesn't compile with the flag COMPILE_FLAG, but the DLL of A, B does compile with this flag. I didn't get any compile error even though my code is trying to convert from different B classes. During my code execution, a_val had garbage field values; actually shifted values.

I would like some explanations on why the C++ compiler didn't warn me from this bug, and also a coding tip of how to improve these #ifdef definitions (I was informed that these fields are used for logging).

Edit: if i would write 2 classes with the same name, each class in a different dll. Then, if i would create a reference between them, i would get a compile error. The preprocesor runs before the compiler, so the compiler can check this redefinition of a class.

I would like some explanations on why the C++ compiler didn't warn me from this bug

How should the compiler warn you? You compiled two different sets, with differing options. Since the class defintion changes, because of these flags, the memory laout is different in each binary. But how would the compiler know this?

Compiling different versions is a perfectly valid scenario, using them properly is up to the programmer/user.

So you have to recompile in all DLLs to the same version, if they are to busing each others definition.

#ifdef is a preprocessor directive. Preprocessing is executed as first part of compilation. Only after preprocessing the normal C++ syntax have to be valid and can be checked.

With your #ifdef you are violating the One Definition Rule : there are two different definitions of class B (with different sizes) in different translation units. The compiler can not detect this. As a conclusion I would say this is a bug in your code. As a coding tip I would suggest compile all files with same compiler settings. In this particular case I would remove the #ifdef .

#ifdef doesn't vary where you are using it. if COMPILE_FLAG is not defines like #define COMPILE_FLAG then the block will not compiled. So, you can not use those variables (line_num, file_name) and you will get if you use them. Those two lines are completely ignored. So, you have to put the codes you used those variable within #ifdef too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM