c++ - 为什么 auto_ptr 似乎违反了 Visual C++ 上的私有(private)继承?

标签 c++ visual-studio private-inheritance

背景信息:这是在 Visual Studio 2008 上检测到的,并在 Visual Studio 2013 上再次得到确认。G++ 对代码尖叫,而 Visual 默默地接受了私有(private)继承漏洞。

因此,在 Visual C++ 上,我们有以下代码:

class Base {};
class Derived : Base {};      // inherits privately. Adding explicitly the
                              //    keyword private changes nothing

int main()
{
   std::auto_ptr<Base>(new Derived) ;   // compiles, which is NOT EXPECTED
   std::auto_ptr<Base> p(new Derived) ; // Does not compile, which is expected
}

为什么第一个(临时的)auto_ptr 会编译?我在调试中进入了它,它确实做了应该用公共(public)继承做的事情(调用正确的构造函数等)

想知道问题是否与 auto_ptr 实现有关(我们永远不知道......),我减少了这个独立代码的问题:

class Base {};
class Derived : Base {};

template <typename T>
class Ptr
{
   T * m_p;

   public :
      Ptr(T * p_p)
         : m_p(p_p)
      {
      }
} ;

int main()
{
   Ptr<Base>(new Derived) ;   // compiles, which is NOT EXPECTED
   Ptr<Base> p(new Derived) ; // Does not compile, which is expected
}

同样,我希望代码不会编译,因为 Derived 是从 Base 私有(private)继承的。

但是当我们创建一个临时文件时,它就起作用了。

我们不能把它归咎于 std::auto_ptr。

我错过了标准中的某些内容(98 或 11 或 14),还是这是一个错误?

最佳答案

Derived* -到- Base*转换,即使继承是私有(private)的,在 C 风格和函数式转换中也是允许的。不,这并不意味着 reinterpret_cast在那种情况下。

这是标准不允许的,但它非常看起来几乎是允许的,所以这是一个微妙的错误。

5.2.3 Explicit type conversion (functional notation) [expr.type.conv]

1 [...] If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4). [...]

5.4 Explicit type conversion (cast notation) [expr.cast]

4 The conversions performed by

  • a const_cast (5.2.11),
  • a static_cast (5.2.9),
  • a static_cast followed by a const_cast,
  • a reinterpret_cast (5.2.10), or
  • a reinterpret_cast followed by a const_cast,

can be performed using the cast notation of explicit type conversion. The same semantic restrictions and behaviors apply, with the exception that in performing a static_cast in the following situations the conversion is valid even if the base class is inaccessible:

  • a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;
  • [...]

在您遇到的情况下,编译器将其解释为 static_cast来自 Derived*auto_ptr<Base> ,在那static_cast ,指向派生类类型对象的指针被转换为明确基类类型的指针。所以看起来标准允许它。

但是,从Derived* 的转换至 Base*是隐式的,它只是恰好作为显式不同转换的一部分执行。所以最后,不行,标准真的不允许。

您可能希望将此报告为错误。来自 Csq的评论,我们了解到有一个 related report ,其中显式 static_cast也允许这种转换,但它并不完全相同。在这种情况下,来自 Derived* 的转换至 Base*是显式的,但在这里是隐式的,Visual C++ 通常在隐式转换中拒绝它。

请注意,在使用多个表达式的函数式转换中,这种误解是不可能的:编译器正确地拒绝了以下内容:

class Base { };
class Derived : Base { };

template <typename T>
class Ptr {
public:
  Ptr(T *a, T *b) { }
};

int main() {
  Ptr<Base>(new Derived, new Derived);
  // error C2243: 'type cast' : conversion from 'Derived *' to 'Base *' exists, but is inaccessible
}

关于c++ - 为什么 auto_ptr 似乎违反了 Visual C++ 上的私有(private)继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27296906/

相关文章:

c++ - 是否可以在 Qt Designer 中使用依赖注入(inject)(对于 .ui 文件)?

c++ - 为什么要私下继承基类,还要名字publicizing?

c++ - 为什么 auto_ptr 似乎违反了 Visual C++ 上的私有(private)继承?

c++ - 编译器是否有可能检测到整数溢出或其他数据类型溢出的可能性?

c++ - Chrono,c++,比较日期

c++ - 返回具有未初始化成员的内联定义结构。 C++

c++ - 分配和检索的括号过载;常量,引用

html - 如何让 VS HTML 编辑器默认为单引号?

c# - Microsoft visual studio 2013 is busy 错误

c++ - 什么是私有(private)继承,它解决了哪些问题?