为什么auto_ptr似乎违反了Visual c++中的私有继承
Why auto_ptr seems to breach private inheritance on Visual C++?
背景信息:在Visual Studio 2008中检测到此问题,并在Visual Studio 2013中再次确认。c++对代码怒吼,而Visual默默地接受了私有继承的破坏。
在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会编译?我在调试时进入了它,它做了一个公共继承应该做的事情(调用正确的构造函数,等等)
想知道问题是否与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。
但是当我们创建一个临时变量时,它可以工作。
我们不能把它归咎于std::auto_ptr。
是否有什么在标准(无论是98或11或14)我错过了,还是这是一个错误?
即使继承是私有的,在c风格和函数强制转换中也允许Derived*
到Base*
的转换。不,在这种情况下,它不是指reinterpret_cast
。
这是标准不允许的,但是非常看起来好像是允许的,所以这是一个微妙的错误。
5.2.3显式类型转换(函数符号)[expr.type.conv]1[…如果表达式列表是单个表达式,则类型转换表达式(在定义上,如果在含义上有定义)与相应的强制转换表达式(5.4)等效。[…]
5.4显式类型转换(强制类型转换表示法)[expr.cast] 执行的转换
- a
const_cast
(5.2.11),- a
static_cast
(5.2.9),static_cast
后接const_cast
,- a
reinterpret_cast
(5.2.10)或reinterpret_cast
后接const_cast
,可以使用显式类型转换的强制转换符号来执行。应用相同的语义限制和行为,但在执行
static_cast
在以下情况下,即使基类不可访问,转换也是有效的:
- 指向派生类类型的对象或派生类类型的左值或右值的指针可以显式地使用分别转换为指向明确基类类型的指针或引用;
- […]
在这种情况下,编译器将其解释为从Derived*
到auto_ptr<Base>
的static_cast
,并且在static_cast
中,指向派生类类型对象的指针被转换为明确的基类类型指针。所以看起来标准是允许的。
然而,从Derived*
到Base*
的转换是隐式的,它只是碰巧作为显式转换的一部分执行。所以最后,不,标准确实不允许。
您可能想要将此报告为bug。从Csq的评论中,我们了解到有一个相关的报告,其中显式的static_cast
也允许这种转换,但它不是完全相同的事情。在这种情况下,从Derived*
到Base*
的转换是显式的,但在这里它是隐式的,visualc++通常在隐式转换中拒绝这种转换。
注意,在使用多个表达式的函数式强制转换中,这种误解是不可能的:编译器会正确拒绝以下语句:
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
}
- Visual Studio 2015:Extern "C" 和 "export" 关键字
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 试图在visual studio上用C++创建一个桌面应用程序
- 如何在MS Visual Studio 2019中运行QT UI
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- Visual Studio Code - C++ Debugger 無法啟動
- Visual C++ constexpr Hints
- 为什么它不适用于Visual 2019的原因
- Visual Studio 2019:插入多个C++风格的单行注释
- Visual Studio Code "undefined reference to `WinMain@16'"
- visual在c++中将十进制数转换为二进制数
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- Visual Studio中的函数声明和函数定义问题
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- Visual C++(VS2017)中用户定义的转换不明确
- Visual C++GC接口如何启用它以及要包含哪个库
- visual是否可以在c++中创建一个接收无限数量相同类型(或至少相当数量)参数的函数
- visual c++,如何获取解决方案目录中的代码
- Visual Studio mkl_link_tool.exe链接错误
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头