c++ 默认移动赋值不能访问受保护的基成员

Posted

技术标签:

【中文标题】c++ 默认移动赋值不能访问受保护的基成员【英文标题】:c++ default move assignment cannot access protected base member 【发布时间】:2018-05-03 08:28:09 【问题描述】:

我有一段代码在启用语言扩展的情况下使用 msvc 编译,但在禁用语言扩展的情况下没有。它分解为这个最小的例子:

class A

    protected:
    A(const A&);
    A& operator=(const A&);
    A(A&&);
    A& operator=(A&&);
;
class B : public A

    public:
    B& operator=(B&&);
;
inline B& B::operator=(B&&) = default; // error C2248

错误信息是

C2248 'A::A': 无法访问在类 'A' 中声明的受保护成员

在第 14 行中定义了移动赋值运算符。有趣的是,下面的代码编译得很好:

class A

    protected:
    A(const A&);
    A& operator=(const A&);
    A(A&&);
    A& operator=(A&&);
;
class B : public A

    public:
    B& operator=(B&&) = default;
;

另外有趣的是,这只发生在 move-assignment-operator 上。 B 的复制赋值操作符以及复制和移动构造函数(但不是移动赋值操作符)可以在类定义、内联和默认值之外定义,并且代码将编译。

我做错了什么?

【问题讨论】:

您使用的是哪个 C++ 版本?使用 VS 2017 和 C++17 可以很好地编译。 GCC 和 Clang 也编译了这个。我可以看到这是 VS 2015 中的一个老错误 在 VisualStudio 2015 Update 3 中无法重现编译错误 @Timo 我正在使用 Visual Studio Professional 版本 14.0.25431.01 Update 3 并为 C++14 进行编译。我不确定我的 Visual Studio 版本是否也告诉你底层编译器的版本。你记得禁用语言扩展吗? 【参考方案1】:

我做错了什么?

什么都没有。

显式默认定义与编译器生成的定义完全相同。在这种情况下,它将移动分配所有基地和成员。当然,这需要您默认的那些基础和成员的移动分配运算符可以访问。由于受到保护,您的也可以访问。

这是一个 MSVC++ 错误。如果可以,请尝试更新到更高版本。

【讨论】:

以上是关于c++ 默认移动赋值不能访问受保护的基成员的主要内容,如果未能解决你的问题,请参考以下文章

受保护的成员不能通过指针或对象 c++ 访问

我无法访问我的基类的受保护成员

C++ 派生类访问属性

为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?

访问派生类中的受保护成员

除了这样,为啥我不能访问受 C# 保护的成员?