admin管理员组

文章数量:1279145

I want to have a macro defined in a class. I wish to define it first in my main, but use an #ifndef to create it if the user chooses not to. For some reason it would seem like the class is being linked before the main, so my #define in main is not being used. TIA

My main ino

#define TEST_MACRO 4
#include "test.h"

test testclass;
void setup() {
  Serial.begin(9600);
  
  testclass.showValue();
}

void loop() {
  
}

test.h

#ifndef TEST_MACRO
  #define TEST_MACRO 5
#endif
#include "Arduino.h"

class test
{
  public:
    test();
    void showValue();
  private:
    uint16_t testval = TEST_MACRO;
};

test.cpp

#include "test.h"

test::test()
{
  ;
}

void test::showValue()
{
  Serial.println(testval);
}

Expected Result "4" Result "5"

However, if I do this with a test.h file include and no class, it all works as expected.

I want to have a macro defined in a class. I wish to define it first in my main, but use an #ifndef to create it if the user chooses not to. For some reason it would seem like the class is being linked before the main, so my #define in main is not being used. TIA

My main ino

#define TEST_MACRO 4
#include "test.h"

test testclass;
void setup() {
  Serial.begin(9600);
  
  testclass.showValue();
}

void loop() {
  
}

test.h

#ifndef TEST_MACRO
  #define TEST_MACRO 5
#endif
#include "Arduino.h"

class test
{
  public:
    test();
    void showValue();
  private:
    uint16_t testval = TEST_MACRO;
};

test.cpp

#include "test.h"

test::test()
{
  ;
}

void test::showValue()
{
  Serial.println(testval);
}

Expected Result "4" Result "5"

However, if I do this with a test.h file include and no class, it all works as expected.

Share Improve this question asked Feb 24 at 5:01 KudapucatKudapucat 1281 silver badge6 bronze badges 6
  • 1 test.cpp doesn't know anything about the macros you've defined in main.ino – Alan Birtles Commented Feb 24 at 5:21
  • I'm not asking it to. I'm asking test.h to. If I don't put in "class test" it works fine. main.ino knows all about the macros defined in test.h I thought the compiler didn't care about files and scope, and just processed #define as it came upon them? ie test.h as follows ``` #ifndef TEST_MACRO #define TEST_MACRO 5 #endif #include "Arduino.h" void showValue() { Serial.println(TEST_MACRO); } ``` Works just fine. – Kudapucat Commented Feb 24 at 6:00
  • 2 The implementation of the initialisation of testval is in test::test at which point the macro is defined to 5 so that's the value you get. You've violated the ODR though so it's undefined behaviour – Alan Birtles Commented Feb 24 at 7:26
  • How does it violate the ODR? That's thrown me completely. Does not the #ifndef cover any ODR violations? I get that the macro is 5, but what I don't get is why it wasn't predefined in Main to be 4. as it was defined before the class was included. I guess this is an integral misunderstanding of mine I'm going tohave to research. If you knew of a resource I can bury myself in reading, I'd appreciate it. – Kudapucat Commented Feb 25 at 10:29
  • 1 uint16_t testval = 4 is a definition, your two cpp files contain different versions of this definition – Alan Birtles Commented Feb 25 at 11:00
 |  Show 1 more comment

1 Answer 1

Reset to default 5

The problem here is that your use of macros means that you have two different versions of the test class. Macros are resolved early on in the compilation process, so this means that in main you have this class

class test
{
    ...
    uint16_t testval = 4;
    ...
};

but in test.cpp you have this class

class test
{
    ...
    uint16_t testval = 5;
    ...
};

The problem here is that C++ does not allow you to have different definitions of a class. Classes included in header files get defined multiple times, but all the definitions must be identical. This is part of what is called the one definition rule (ODR).

Programs that violate ODR have undefined behaviour and furthermore compilers are not required to diagnose the violation, so you cannot expect to see any compiler or run time error message. Instead you just get unpredictable behaviour from your code.

It's not clear to me what real world problem you are trying to solve using this approach, but it cannot work due to the ODR violation. Perhaps you should explain what you are actually trying to achieve, and ask for suggestions on how to do that. Maybe a template class would fulfil your needs?

本文标签: cArduino Macros not working as expected with ClassesStack Overflow