# c++, Not being able to include more then 1 family class

## Recommended Posts

Hello.

I am aware the title is a bit off but here is what i need.

class JSon1 {/*Unable to be included with JSon2*/};
class JSon2 {/*Unable to be included with JSon1*/};
class SSon1 {/*Unable to be included with SSon2*/};
class SSon2 {/*Unable to be included with SSon1*/};

class Base1 : public: JSon1, SSon1 {}; // valid
class Base2 : public: JSon1, JSon2 {}; // invalid
class Base3 : public: JSon1 {}; // valid
class Base4 : public: SSon1, SSon2 {}; // invalid


I will have classes of opposite functioning, so i want to protect the coder somehow so its not possible including the classes i want to mark as opposite.

Currently i know no way of doing this except trying to overload some operator witch i haven't think off yet.

##### Share on other sites
Off the top of my head, one way to do this is to have your mutually exclusive classes virtually inherit from a common base class. Give that base class a virtual function and have both your mutually exclusive classes implement that function. When a class tries to inherit from both of them, it won't know which to use so you'll get a compiler error. For example:
struct VirtualBase {
virtual void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) = 0;
virtual ~VirtualBase() {}
};

struct A : virtual VirtualBase {
void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct B : virtual VirtualBase {
void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct C : A, B {}; // some sort of ambiguous inheritance error

This has a run time cost, so I would classify this as a cure worse than the disease.

##### Share on other sites

Off the top of my head, one way to do this is to have your mutually exclusive classes virtually inherit from a common base class. Give that base class a virtual function and have both your mutually exclusive classes implement that function. When a class tries to inherit from both of them, it won't know which to use so you'll get a compiler error. For example:

struct VirtualBase {
virtual void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) = 0;
virtual ~VirtualBase() {}
};

struct A : virtual VirtualBase {
void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct B : virtual VirtualBase {
void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct C : A, B {}; // some sort of ambiguous inheritance error

This has a run time cost, so I would classify this as a cure worse than the disease.

You could use conditional compilation though and just use virtual inheritance for debug builds since its never actually used for anything other than catching incorrect usage of the classes.

Edited by SimonForsman

##### Share on other sites

I wouldn't use virtual inheritance in a debug build to force an error, it doesn't communicate the intention of the code at all.

What you need is conditional compilation. You can do it easily with include guards

in Json1.h

#ifndef JSON1_H_INCLUDED

#define JSON1_H_INCLUDED

#ifdef JSON2_H_INCLUDED

#error JSon2.h must not be included in files which include JSon1.h

#endif

#endif //JSON1_H_INCLUDED

In JSon2.h

#ifndef JSON2_H_INCLUDED

#define JSON2_H_INCLUDED

#ifdef JSON1_H_INCLUDED

#error JSon1.h must not be included in files which include JSon2.h

#endif

#endif //JSON2_H_INCLUDED

Clear, and gives an unambiguous error message.

##### Share on other sites

It also prevents a lot more than just inheritance. You could never use those two classes in the same header or same source file in any part of your code.

##### Share on other sites

There are circumstances where you could end up including the two files, without necessarily creating the kind of inheritance structure that BaneTrapper wants to avoid. An example might be a factory that instantiates one of the two implementations:

#include "client1.hpp"
#include "cient2.hpp"

std::shared_ptr<Client> make_client(Condition condition) {
if(condition) {
return std::make_shared<ClientOne>(/* ... */);
}
return std::make_shared<ClientTwo>(/* ... */);
}


However, if it is the case where the user is supposed to choose one of two implementations globally, then maybe such an approach makes sense.

##### Share on other sites

Its probably better to not protect the programmer, and just document for them that these configurations should be avoided. In fact, such "protection" is often a sign of lazy implementation on your part that just doesn't want to deal with certain cases -- this is one of the problems with the Singleton pattern, for instance. Nat saying that's necessarilty the case here, but be honest and ask yourself if it is, or if those things really are mutually exclusive.

Another way of providing protection would possibly be to only allow construction through a factory that only allows legitimate combinations to be created.

##### Share on other sites

Not to limit the programmer, and only document, thanks on tip.

Thanks on all protection ideas i will see what i come up with at end.

##### Share on other sites

Its probably better to not protect the programmer, and just document for them that these configurations should be avoided.

I have to disagree entirely. Your code and the interfaces to said code ought to designed in a way that prevents any potential misuse and mistakes by programmers that need to make use of them. Having to document gotchas because you didn't bother to design properly is a sign of lazy implementation on your part, not the other way around.

If there's something you don't want programmers to do with your code, do what you can to prevent it.

Edited by Indifferent

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
627738
• Total Posts
2978881

• 10
• 10
• 21
• 14
• 13