Search code examples
c++virtualderived

use protected ctor from virtual base class in derived class


I have an abstract pseudo base class for some audio formats with 2 ctors - one works for the derived class but the other one gives me an error which i can´t solve. It says that i can´t access the protected member declared in MP3, but why can it reach one ctor but not the other?

class Audioformat
{
protected:
    string song="";
    Audioformat(string s) :song(s) {};//This ctor gives me the error
    Audioformat() { song = "unknown";}
public:
    virtual void play()=0;
    virtual void info() = 0;
    virtual ~Audioformat() = 0 {};
};
class MP3 : public Audioformat
{
public:
    using Audioformat::Audioformat;
    void play() { cout << "pseudo-play" << endl; }
    void info() { cout << song << endl; }
    ~MP3() { cout << "MP3" << endl; delete this; }
};

Here´s my main :

int main()
{

    MP3 song1{};//WORKS
    MP3 song2{ "random trash song" };//ERROR    MP3::MP3(std::string) is inaccessible
    play(song1);
    info(song1);
    getchar();
    return 0;
}

Solution

  • Two reasons:

    1. Using declarations alone do not suppresses the implicit declaration of a special class member. In this case the default c'tor ([namespace.udecl]/4):

      the using-declaration does not by itself suppress the implicit declaration of the derived class member

      So a public default c'tor for MP3 is synthesized by the compiler, and invoked in your example.

    2. The c'tors introduced by a using declaration basically have the same accessibility they had in the base class ([namespace.udecl]/19):

      A using-declarator that names a constructor does not create a synonym; instead, the additional constructors are accessible if they would be accessible when used to construct an object of the corresponding base class, and the accessibility of the using-declaration is ignored.

      So the c'tor taking a string is not accessible in main since it's protected in MP3 as well.

    If you want to have a public c'tor in MP3 that accepts a std::string you have to define it in full, and forward to the base class c'tor explicitly:

    public:
      MP3(std::string s) : Audioformat(s) {}