Inherit class optional using #ifdef

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it possible to optionally inherit a class i.e. if somethings defined?

 

An example that doesn't seem to work:

 

class myclass
#ifdef SWITCH
: public mybaseclass
#endif

{

}

Last Edited: Wed. Jun 6, 2018 - 08:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But the whole point of inheritance is that the derived class inherits the base class's methods/data. If you make this "switchable" what about all the code that is also inherited from mybaseclass too? In fact the chances are that the base defines interfaces as pure vrtual methods so the derived class is going to have implementations of methods that are no longer defined from the base?

 

Take a step back and say what it is you are really trying to achieve here. Why would it ever make much sense to make the base a conditional compilation?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes you are correct, I want the option to not inherit some or all base classes(data and methods), pure virtual functions are not a worry because by removing them from the derived class potentially orphins the base class(will still compile), yes I also need to remove code calling the base class's methods from the derived class, there will be a few #ifdef's for that. As for accessing private or protected data I'm not anyway.

Looking for an automated toggle to save me disabling code in multiple places. All works fine except the question at hand, how to remove the base class from the derived using a "switch".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But this is just a compile time choice? If so what's wrong with the method you are already proposing? (obviously do the #define as a -D so it affects all files!)

 

But I still don't get it - the whole point of inheritance is so that the derived class can use all that has already been written/tested in the base. If that functionality is not coming from the base then you are going to need a full implementation in this new class which means you end up having the same stuff in two places which is the whole reason for inheritance - to avoid that happening?!? Now you have to apply maintenance in two places.

Last Edited: Tue. Jun 5, 2018 - 12:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can use conditional compilation if you want.   It should work just fine.

Note that all your modules must be treated equally.

 

OTOH, as Cliff has said:   think carefully about what you are doing.

 

David.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes compile time is what I'm after, runtime doesn't sound practical/possible... What do you mean by #define as a -D 

 

The #ifdef in my example doesn't seem to work, plus it would fail when there's no base class's left, how do you deal with the ":"?

 

Not using inheritance for reusing code, well kind of am... (not as you describe). More for reusing completely different polymorphic objects(classes).

 

what's conditional compilation? never heard of it, where do I get info on it? How's it work?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

savman wrote:
What do you mean by #define as a -D
When you build C you have two options:

#define TARGET_PORT PORTB

int main(void) {
    TARGET_PORT = 0x55;
}

In this the #define is in one of the source files. The problem comes if more than one of the source files need to see this #define. You can achieve that by putting it into a .h that is shared across the project - but there's a possibility you might write another source where you forget the #include. So the other option is this:

int main(void) {
    TARGET_PORT = 0x55;
}
avr-gcc -mmcu=atmega16 -O -DTARGET_PORT=PORTD avr.c -o avr.elf

In this the define is being made on the command line instead. If the same command line is used to build all the files in the project (as usually happens when a Makefile is used) then the same -D gets passed to all the files every time - so nothing misses the fact that TARGET_PORT=PORTD. In your case it would simply be:

avr-gcc -mmcu=atmega16 -O -DSWITCH avr.c -o avr.elf

on the occasion you want to build with the define made (and "SWITCH" is a terrible name by the way - don't use C keywords as symbol names even if the case is different!)

savman wrote:
what's conditional compilation? never heard of it, where do I get info on it? How's it work?
Well it seems you just "invented it" without knowing what it is! "Conditional compilation" just means exactly what you are doing - having some of the code only built if some pre-pro macro is defined. A common one is:

int add(int a, int b) {
#ifdef DEBUG
    printf("add %d + %d\n", a, b);
#endif
    return a + b;
}

The printf here is conditionally compiled depending on the defined state of "DEBUG".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
class myclass
#ifdef SWITCH
: public mybaseclass
#endif
{
   ...
}

will become

class myclass
{
   ...
}

or

class myclass : public mybaseclass
{
   ...
}

C  and C++ does not mind newlines or whitespace.   The #if mechanism works with whole lines.   Hence the conditional compilation.    The Compiler receives different lines from the C preprocessor.

 

You normally use conditional compilation for different targets e.g. ATmega1284 or SAMD21G18A

Or for debugging.    Note that Release and Debug configurations omit or add -DDEBUG to the compiler.   Look in Properties->Symbols

 

However your H file and CPP file need to see the same thing for SWITCH.   This means that you should add SWITCH to the Project Symbols and not a local file.

 

I suspect that you are from a younger generation.   Cliff (and I) grew up with regular command line tools.   You add a global #define to a command with the -D option.    The IDE hides this from you  but you can always look in the Output Window.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
The IDE hides this from you
In AS7 there's a project section called "Symbols" (I think it was) which is where you enter things that it will then use as -D's

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,  and you have to be VERY careful.

 

AS7 has different Symbols entries for C, C++, ASM.   And it defaults to "Active (Debug)" configuration.

 

In practice,  you want a Global #define for the whole project e.g. F_CPU

I always set the configuration to "All Configurations" and still have to set F_CPU for C and C++

You do not want Release to have different "environment"

 

Different IDEs allow you to set options for project-wide, logical-group, individual files e.g. by right-clicking on the appropriate node.

 

AS7 has its own way of doing things.

YMMV.

 

David.

Last Edited: Wed. Jun 6, 2018 - 09:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Went back and double tested it, works fine when not defined.

SWITCH is not the actual name, I got that name from you guys lol

 

When I define -DSWITCH in symbols or common header file, this doesn't compile:

 

class myclass
#ifdef SWITCH
: public mybaseclass
#endif
{
   …
}

 

This does compile:

 

class myclass
//#ifdef SWITCH
: public mybaseclass
//#endif
{
   …
}

 

Out of interest I tried:

 

class myclass :
#ifdef SWITCH
public mybaseclass
#endif
{
   …
}

 

and I get a compile error:

 

Error  expected class-name before '{' token UC3

 

AS4 was my first introduction to AVR, before that I was writing asm for PIC back at school, forget what the compiler was... EDIT; PICALL was the compiler

Last Edited: Wed. Jun 6, 2018 - 10:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You invent SWITCH in #1. It is an inappropriate name for a symbol.
.
I don't believe you. I will try it later.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I went back in time and re-named what I had lol

 

Cheers

Last Edited: Wed. Jun 6, 2018 - 10:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

savman wrote:
Error expected class-name before '{' token UC3
Not enough to go on. It's probably what comes next within the class declaration. I rather suspect that it might be a reference to something defined in the base. IOW something like:

// base.h
class base {
    typedef int foo;
}
// derived.h
#ifdef SWITCH
#include "base.h"
#endif

class derived
#ifdef SWITCH
: base
#endif
{
    foo n;
}

With SWITCH not defined the compiler will encounter a "foo" it doesn't know

Last Edited: Wed. Jun 6, 2018 - 11:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This when defined, was giving an error that it couldn't find a function from in the base class, so it wasn't inheriting:

 

class myclass
#ifdef SWITCH
: public mybaseclass
#endif
{
   …
}

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

savman wrote:
This when defined, was giving an error that it couldn't find a function from in the base class, so it wasn't inheriting:
namespace issue perhaps?

 

PS Using --save-temps and studying the .i files is probably called for so you can see what the compiler actually sees.

Last Edited: Wed. Jun 6, 2018 - 11:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But this did compile:

 

class myclass
//#ifdef SWITCH
: public mybaseclass
//#endif
{
   …
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggest that you post the real source code. Then someone might spot the problem.
.
I could post an example but you will not believe it.
.
The C preprocessor does text substitution according to well defined rules.
Either process by hand or inspect the intermediate file as Cliff suggested in #16.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What does it mean when the *.ii file is not there?

All there but the one I'm interested in

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Then the source for which you expecting a .ii was presumably not compiled.