Develop Biology
The language of life
bio::VirtualBase Class Referenceabstract

#include <VirtualBase.h>

+ Inheritance diagram for bio::VirtualBase:

Protected Member Functions

 VirtualBase ()
 
virtual ~VirtualBase ()
 
void Initialize (ByteStream arg1)
 
void Initialize (ByteStream arg1, ByteStream arg2)
 
void Initialize (ByteStream arg1, ByteStream arg2, ByteStream arg3)
 
void Initialize (ByteStreams args)
 
virtual void InitializeImplementation (ByteStreams args)=0
 

Protected Attributes

bool m_hasBeenInitialized
 

Detailed Description

NOTE: inheriting from VirtualBase is only necessary if your class will be virtually inherited and implements non-default constructors.

C++ has a problem: virtually inherited classes are instantiated by the most derived class, bypassing all other initializers. Because we want our most derived classes to be simpler, not more complex, we either have to rely on a chaotic mesh of last-to-write setter calls in intermediate class constructors or do what we've done here. VirtualBase does 1 thing and that is to fix the problem above. Here's how we do this: First, the child class of VirtualBase should PROTECTEDLY inherit VirtualBase (i.e class MyClass : protected VirtualBase). Next, that child should implement InitializeImplementation(), taking each arg as if it were provided to the class constructor. Lastly, children of the child class, which virtually inherit this child of VirtualBase, should call ChildClass::Initialize(args), where ChildClass is the name of the child class and args are all of the arguments necessary to initialize the child. NOTE: unlike normal c++ constructors, no args can be left out of the Initialize args list and both order and type must be perfectly aligned with what the child class expects. Unfortunately, because all this happens at run time, there are no compile-time type checks.

When multiple child classes all call Initialize on a virtually inherited parent, only the FIRST call will take effect. All others will be ignored (but you can fall back on chaotic setter calls to overcome this). By inverting the way virtually inherited construction works, we can rely on passing arguments to a base class in order to virtual base class, restoring normal derived->base initialization behavior.

To illustrate how this works: [furthest derived class] -—> [virtual base default ctor] (implicit) [furthest derived class] -—> [parent class 1 ctor] -—> [grandparent 1 ctor] [furthest derived class] -—> [parent class 2 ctor] -—> [(virtual base)::Initialize()] [furthest derived class] -—> [parent class 3 ctor] -—> [(virtual base)::Initialize()] In this example, only "parent class 2" gets to Initialize the virtual base. "Parent class 3" does not get to Initialize the virtual base. "Furthest derived class" elects "parent class 2" as the Initializer based on it's inheritance order ("parent class 2" comes first). If we change up the order and have "grandparent 1" call Initialize, we'll have to make sure "parent class 1" passes the appropriate arguments to the "grandparent 1" ctor. Passing arguments to the Initializing parent is thus the key to making this system work without needing to have the "furthest derived class" include the virtual base in its initializer list.

Definition at line 52 of file VirtualBase.h.

Constructor & Destructor Documentation

◆ VirtualBase()

bio::VirtualBase::VirtualBase ( )
protected

Definition at line 27 of file VirtualBase.cpp.

28 :
30{
31
32}
bool m_hasBeenInitialized
Definition: VirtualBase.h:112

◆ ~VirtualBase()

bio::VirtualBase::~VirtualBase ( )
protectedvirtual

Definition at line 34 of file VirtualBase.cpp.

35{
36
37}

Member Function Documentation

◆ Initialize() [1/4]

void bio::VirtualBase::Initialize ( ByteStream  arg1)
protected

Ease-of-use calls for wrapping c++98 vector initialization. Calls Initialize(ByteStreams).

Parameters
arg1

Definition at line 48 of file VirtualBase.cpp.

49{
51 return);
52 ByteStreams args;
53 args.push_back(arg1);
54 Initialize(args);
55}
#define BIO_SANITIZE_AT_SAFETY_LEVEL_2(test, success, failure)
void Initialize(ByteStreams args)
Definition: VirtualBase.cpp:40
std::vector< ByteStream > ByteStreams
Definition: Types.h:52

References BIO_SANITIZE_AT_SAFETY_LEVEL_2, Initialize(), and m_hasBeenInitialized.

◆ Initialize() [2/4]

void bio::VirtualBase::Initialize ( ByteStream  arg1,
ByteStream  arg2 
)
protected

Ease-of-use calls for wrapping c++98 vector initialization. Calls Initialize(ByteStreams).

Parameters
arg1
arg2

Definition at line 57 of file VirtualBase.cpp.

61{
63 return);
64 ByteStreams args;
65 args.push_back(arg1);
66 args.push_back(arg2);
67 Initialize(args);
68}

References BIO_SANITIZE_AT_SAFETY_LEVEL_2, Initialize(), and m_hasBeenInitialized.

◆ Initialize() [3/4]

void bio::VirtualBase::Initialize ( ByteStream  arg1,
ByteStream  arg2,
ByteStream  arg3 
)
protected

Ease-of-use calls for wrapping c++98 vector initialization. Calls Initialize(ByteStreams).

Parameters
arg1
arg2
arg3

Definition at line 70 of file VirtualBase.cpp.

75{
77 return);
78 ByteStreams args;
79 args.push_back(arg1);
80 args.push_back(arg2);
81 args.push_back(arg3);
82 Initialize(args);
83}

References BIO_SANITIZE_AT_SAFETY_LEVEL_2, Initialize(), and m_hasBeenInitialized.

◆ Initialize() [4/4]

void bio::VirtualBase::Initialize ( ByteStreams  args)
protected

Calls InitializeImplementation once and then becomes a nop.

Parameters
args

Definition at line 40 of file VirtualBase.cpp.

41{
43 return);
46}
virtual void InitializeImplementation(ByteStreams args)=0

References BIO_SANITIZE_AT_SAFETY_LEVEL_2, InitializeImplementation(), and m_hasBeenInitialized.

Referenced by bio::physical::Symmetry::Symmetry(), bio::physical::Identifiable< DIMENSION >::BIO_DISAMBIGUATE_ALL_CLASS_METHODS(), and Initialize().

◆ InitializeImplementation()

Member Data Documentation

◆ m_hasBeenInitialized

bool bio::VirtualBase::m_hasBeenInitialized
protected

false until Initialize is called, then true forever more. This could be private but is left accessible to children in case hacks become necessary.

Definition at line 112 of file VirtualBase.h.

Referenced by Initialize().


The documentation for this class was generated from the following files: