在没有继承的类中,我预计该virtual
关键字不会产生明显的影响。但是,在下面的代码示例中,添加它会破坏编译。我想了解背后的机制。为什么该virtual
关键字会破坏编译?
没有 virtual 关键字它编译得很好。
#define USE_VIRTUAL 1
// compile with: cl /W4 /EHsc main.cpp /link /out:main.exe
#include<iostream>
#include<memory>
struct Dummy {int i = 3;};
class Uncopyable {
public:
// Implicitly delete the copy constructor by having
// a non-copyable member.
std::unique_ptr<Dummy> m_innerPtr;
// A virtual destructor to allow correct inheritance.
// I first thought that this implicitly deletes the
// copy-assignment and copy-constructor,
// but it does not. It does, however, implicitly
// delete the move constructor and assignment.
virtual ~Uncopyable() = default;
// accessible constructor
Uncopyable() = default;
Uncopyable(std::unique_ptr<Dummy> dummy):m_innerPtr(std::move(dummy)){};
};
template <typename MaybeCopyable>
class Bamboozle {
public:
void foo(std::shared_ptr<MaybeCopyable> obj) {
std::cout << "Reached Bamboozle::foo(shared_ptr)" << std::endl;
}
// overload that takes an object by value
#if USE_VIRTUAL
virtual
#endif
void foo(MaybeCopyable obj){
std::cout << "Reached Bamboozle::foo(Uncopyable)" << std::endl;
foo(std::make_shared<Uncopyable>(std::move(obj)));
}
};
int main(int argc, char** argv){
// construct param objects
std::shared_ptr<Uncopyable> uncSharedPtr = std::make_shared<Uncopyable>();
// prints Bamboozle::foo(shared_ptr)
Bamboozle<Uncopyable> bamboozleObj;
bamboozleObj.foo(uncSharedPtr);
return 0;
};
如果您想了解我认为与此有关的其他方面,请参阅此问题(由于太详细而关闭)以了解更多背景信息。特别是模板和移动构造函数。类模板是重现此行为所必需的。
错误消息是:
cl /W4 /EHsc main.cpp /link /out:main.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33134 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
main.cpp
main.cpp(46): warning C4100: 'argv': unreferenced formal parameter
main.cpp(46): warning C4100: 'argc': unreferenced formal parameter
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xutility(255): error C2280: 'Uncopyable::Uncopyable(const Uncopyable &)': attempting to reference a deleted function
main.cpp(24): note: compiler has generated 'Uncopyable::Uncopyable' here
main.cpp(24): note: 'Uncopyable::Uncopyable(const Uncopyable &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::unique_ptr<Dummy,std::default_delete<Dummy>>::unique_ptr(const std::unique_ptr<Dummy,std::default_delete<Dummy>> &)'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\memory(3319): note: 'std::unique_ptr<Dummy,std::default_delete<Dummy>>::unique_ptr(const std::unique_ptr<Dummy,std::default_delete<Dummy>> &)': function was explicitly deleted
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xutility(255): note: the template instantiation context (the oldest one first) is
main.cpp(51): note: see reference to class template instantiation 'Bamboozle<Uncopyable>' being compiled
main.cpp(38): note: while compiling class template member function 'void Bamboozle<Uncopyable>::foo(MaybeCopyable)'
with
[
MaybeCopyable=Uncopyable
]
main.cpp(40): note: see reference to function template instantiation 'std::shared_ptr<Uncopyable> std::make_shared<Uncopyable,Uncopyable>(Uncopyable &&)' being compiled
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\memory(2769): note: see reference to function template instantiation 'std::_Ref_count_obj2<_Ty>::_Ref_count_obj2<_Ty>(_Ty &&)' being compiled
with
[
_Ty=Uncopyable
]
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\memory(2094): note: see reference to function template instantiation 'void std::_Construct_in_place<_Ty,_Ty>(_Ty &,_Ty &&) noexcept(false)' being compiled
with
[
_Ty=Uncopyable
]
添加析构函数会默默地移除移动构造函数和移动赋值。它应该也会移除复制构造函数和复制赋值,但目前并没有这样做(这已被弃用),因此移动这样的类会默默地复制它。
您的类没有可供回退的复制操作,因此当它失去移动操作时,它就变得不可移动。
添加这个:
至于为什么添加
virtual
会破坏事情。virtual
强制函数无条件实例化,而非虚函数只有在使用时才会实例化,并且您不能调用有问题的函数。