简体   繁体   中英

Is it necessary to have default ctor for the most-base class in virtual inheritance?

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 the VBoardAcquisitor
  • 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 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM