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.
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
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 :
VBoard
ctor with some random address in the init-list of the VBoardAcquisitor
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?
OS : Scientific Linux 7
gcc version : 4.8.5
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 class VBoardAcquisitor
, which itself will forward the address to VBoard
Here is the constructor of V1785N
V1785N( int address ) :
VBoardAcquisitor(address)
{}
and the constructor of VBoardAcquisitor
VBoardAcquisitor(int address) :
VBoard( address ),
buffer( nullptr )
{ }
Note that you should not inherit with virtual
from VBoard
, so the first line of VBoardAcquisitor
looks like
class VBoardAcquisitor : public VBoard
The full code: https://ideone.com/YUeLtf
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.