Preliminaries
I am writing a high level library for VMEbus modules. I have two levels of abstraction to represent modules:
|---------------------|
| VBoard |
|---------------------|
| + VBoard( address ) |
| + Init() = 0 |
| + ... |
|---------------------|
/\ /\
/__\ /__\
|| ||__________________________
|| ||
|--------------------| |-----------------------|
| VBoardAcquisitor | | VBoardInterrupter |
|--------------------| |-----------------------|
| + AllocBuff() = 0 | | ... |
| + ... | |-----------------------|
|--------------------| /\
/\ /__\
/__\ ______ may be _____________||
|| ||
.________________________.
| |
| V1785N |
|________________________|
| + Init() override |
| + AllocBuff() override |
|________________________|
So every concrete module (as V1785N
in the above UML diagram) is a VBoard
and has to override the Init()
function (and some others). Also there are modules endowed with data acquisition functions. For them there is another interface (abstract class) named VBoardAcquisitor
which is, of course, also a VBoard
. There may be more intermediate classes (like VBoardInterrupter
) between the VBoard
and the concrete module. So virtual inheritance.
Problem
The crucial moment is that VBoard
does have only parametrized constructor (parameter is the VME address of a module). And I don't want it to have other one (copy-assignment and copy-ctor are deleted). But when implementing the above scheme in C++ (see Code section) I get compilation error:
Code.cpp: In constructor ‘VBoardAcquisitor::VBoardAcquisitor()’:
Code.cpp:22:29: error: no matching function for call to ‘VBoard::VBoard()’
buffer( nullptr )
^
Code.cpp:22:29: note: candidates are:
Code.cpp:8:9: note: VBoard::VBoard(int)
VBoard( int address ) :
^
Code.cpp:8:9: note: candidate expects 1 argument, 0 provided
Code.cpp:3:7: note: constexpr VBoard::VBoard(const VBoard&)
class VBoard
^
Code.cpp:3:7: note: candidate expects 1 argument, 0 provided
Code
This is the MRE (compiles with g++ -std=c++11 Code.cpp -o Code
):
#include <iostream>
class VBoard
{
int address;
public :
VBoard( int address ) :
address( address )
{ }
virtual ~VBoard() { };
virtual void Init() = 0;
};
class VBoardAcquisitor : virtual public VBoard
{
int *buffer;
public :
VBoardAcquisitor() :
buffer( nullptr )//problem here
{ }
virtual ~VBoardAcquisitor() { };
virtual void AllocBuff() = 0;
};
class V1785N : public VBoardAcquisitor
{
public :
V1785N( int address ) :
VBoard( address ),
VBoardAcquisitor()
{ }
~V1785N() { }
void Init() override { std::cout << "Init\n"; }
void AllocBuff() override { std::cout << "AllocBuff\n"; }
};
int main()
{
V1785N adc( 0x40000000 );
return 0;
}
It compiles fine if I either :
- call to the
VBoard
ctor with some random address in the init-list of theVBoardAcquisitor
- define default ctor of
VBoard
Although I know (checked) that such a call from VBoardAcquisitor
(the first case) will be ignored I don't like that because I am kind of forced to use some "default" board address and at least aesthetically I am not comfortable with that.
So my question is : Are the only possible "solutions" are those two?
System
OS : Scientific Linux 7
gcc version : 4.8.5
Note
Note that it compiles fine with gcc 7.5.0
as is on Ubuntu 18.04. But I don't know why.
The constructor of
V1785N
should forward the address to it's base classVBoardAcquisitor
, which itself will forward the address toVBoard
Here is the constructor of
V1785N
and the constructor of
VBoardAcquisitor
Note that you should not inherit with
virtual
fromVBoard
, so the first line ofVBoardAcquisitor
looks likeThe full code: https://ideone.com/YUeLtf