在派生类中使用来自虚拟基类的protected ctor

时间:2017-12-03 13:01:12

标签: c++ virtual derived

我有一个抽象的伪基类用于一些带有2个ctors的音频格式 - 一个用于派生类,但另一个给我一个我无法解决的错误。 它说我无法访问MP3中声明的受保护成员,但为什么它可以到达一个ctor而不是另一个?

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; }
};

这是我的主要内容:

int main()
{

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

1 个答案:

答案 0 :(得分:4)

有两个原因:

  1. 单独使用声明不会抑制特殊类成员的隐式声明。在这种情况下,默认c'tor([namespace.udecl]/4):

      

    using-declaration本身不会抑制隐式   派生类成员的声明

    因此MP3的公共默认c'tor由编译器合成,并在您的示例中调用。

  2. using声明引入的c'tors基本上具有与基类([namespace.udecl]/19)相同的可访问性:

      

    用于命名构造函数的using-declarator   没有创建同义词;相反,额外的构造函数是   如果在用于构建时可以访问它们,则可访问   对应基类的对象,以及对象的可访问性   使用声明被忽略。

    因此main无法访问带字符串的c'tor,因为它在MP3中也受到保护。

  3. 如果您希望MP3中的公共c'tor接受std::string,您必须完整定义它,并明确转发到基类c'tor:

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