[英]why shared_ptr can access with ingoring the “protected access right”
I made some testing with shared_ptr,and i can't think out the matter below.I just started to learn the boost library. 我用shared_ptr做了一些测试,我想不出下面的事情。我刚开始学习boost库。 Is there anybody can tell me the reason?
有人可以告诉我原因吗?
#include <boost\shared_ptr.hpp>
#include <iostream>
class A
{
public:
virtual void sing()
{
std::cout<<"A";
}
protected: virtual ~A() {};
};
class B : public A
{
public:
virtual void sing()
{
std::cout << "B";
}
virtual ~B() {};
};
int foo()
{
boost::shared_ptr<A> pa(new B());
pa->sing();
delete static_cast<B*>(pa.get());
delete pa.get(); //this line has a problem error C2248: “A::~A”: can't access protected memmber(declared in class“A")
return 0;
}
int main()
{
foo();
return 0;
}
but it can be compiled when that line is commented out. 但是当该行被注释掉时它可以被编译。 Surely it doesn't mean that the shared_ptr will delete the pointer internally maintained out of the main function, just like what i did.
当然,这并不意味着shared_ptr将删除内部维护的主函数之外的指针,就像我所做的那样。 Is there any difference between the pointer returned by
pa.get()
and the pointer internally maintained? pa.get()
返回的指针和内部维护的指针之间有什么区别吗?
I believe that delete
is called during destruction of the shared_ptr
on the type of the pointer passed into the constructor. 我相信在传递给构造函数的指针类型的
shared_ptr
销毁期间会调用delete
。 Have a look at the constructor here: 看看这里的构造函数:
http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_ptr.htm#constructors http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_ptr.htm#constructors
So when your pa
goes out of scope, B::~B( )
is called rather than the destructor of the type contained - A::~A
( which would be impossible because it's declared protected
). 所以当你的
pa
超出范围时,调用B::~B( )
而不是包含的类型的析构函数 - A::~A
(这是不可能的,因为它被声明为protected
)。
Actually, it's a bit more complicated than that: the machinery behind shared_ptr
is quite complicated. 实际上,它有点复杂:
shared_ptr
背后的机制非常复杂。
First, let us prove there is no specific access rights granted to shared_ptr
: 首先,让我们证明没有授予
shared_ptr
特定访问权限:
int main() {
A* a = new B();
std::shared_ptr<A> p(a); // expected-error
}
This will result in an error because the destructor of A
is not accessible. 这将导致错误,因为无法访问
A
的析构函数。 Interestingly, the error occurs at the point of construction, which is a clue... 有趣的是,错误发生在构造点,这是一个线索......
So, what is the magic behind shared_ptr
? 那么,
shared_ptr
背后的魔力是什么?
Internally, a shared_ptr
keeps much more than a simple pointer and reference counts. 在内部,
shared_ptr
比简单的指针和引用计数要多得多。 A shared_ptr
is built with a deleter
, in charge of destructing the instance of the object. shared_ptr
是用deleter
构建的,负责破坏对象的实例。 Where the design really shines is that this deleter
is instantiated in the constructor and thus may know more type information than the bare shared_ptr
type lets on. 设计真正闪耀的地方是这个
deleter
器在构造deleter
中实例化,因此可能知道比裸shared_ptr
类型更多的类型信息。
A simplified demo: 简化演示:
template <typename T>
struct shared_holder {
typedef void (*Disposer)(T*);
explicit shared_holder_base(T* t, Disposer d): _ptr(t), _disposer(d) {}
void dispose() { _disposer(_ptr); _ptr = 0; }
T* _ptr;
Disposer _disposer;
};
template <typename U, typename T>
void dispose(T* t) { delete static_cast<U*>(t); }
template <typename T>
class shared_ptr {
typedef shared_holder<T> holder;
public:
shared_ptr(): _holder(0), _ptr(0) {}
template <typename U>
explicit shared_ptr(U* u):
_holder(new holder(u, dispose<U, T>)), _ptr(_holder->_ptr) {}
private:
holder* _holder;
T* _ptr;
};
The key insight is that the disposer is instantiated from the static type known by the constructor; 关键的见解是处理器是从构造函数已知的静态类型实例化的; this is why:
这就是为什么:
shared_ptr<A>(new B)
works shared_ptr<A>(new B)
有效 A* a = new B; shared_ptr<A>(a)
A* a = new B; shared_ptr<A>(a)
does not A* a = new B; shared_ptr<A>(a)
没有 You can read the Boost headers, the machinery behind the shared_ptr
is quite interesting. 你可以阅读Boost标题,
shared_ptr
背后的机制非常有趣。
As an exercise for the reader, why does shared_ptr<T>
has a _ptr
member ? 作为读者的练习,为什么
shared_ptr<T>
有_ptr
成员?
When you have: 当你有:
boost::shared_ptr<A> pa(new B());
...you are calling boost::shared_ptr
constructor and are dealing with TWO template parameters: ...您正在调用
boost::shared_ptr
构造函数并处理两个模板参数:
shared_ptr template type T
( A
in your case); shared_ptr模板类型
T
(在您的情况下为A
);
get()
returns T*
so when you tried: 当你尝试时,
get()
返回T*
delete pa.get();
...you tried to access ~A()
which is accessible only to A
s children and therefore got an error. ...您尝试访问
~A()
这是只访问A
的孩子,因此得到了一个错误。
In the following line: 在以下行中:
delete static_cast<B*>(pa.get());
...you were downcasting A*
to B*
and called delete on B*
thus invoking ~B()
to which you had access. ......你向下转换
A*
到B*
,并要求删除B*
从而调用~B()
到你有机会访问。 ( ~B()
is always calling ~A()
for ~A()
is declared as virtual
) (
~B()
总是调用~A()
表示~A()
被声明为virtual
)
shared_ptr constructor argument template type Y
( B
in your case) with the requirement that Y*
must be convertible to T*
(you can upcast B*
to A*
as B
inherits A
in your case). shared_ptr构造函数参数模板类型
Y
(在您的情况下为B
),要求Y*
必须可转换为T*
(您可以将B*
向上转换为A*
因为B
在您的情况下继承A
)。
~shared_ptr()
calls delete
on Y*
( B*
in your case; ~B()
can access ~A()
and calls it) and this is what happens when pa
goes out of scope (and this is how shared_ptr
accessed base class protected destructor which was your original question). ~shared_ptr()
在Y*
上调用delete
(在你的情况下是B*
; ~B()
可以访问~A()
并调用它)这就是当pa
超出范围时会发生的事情(这就是shared_ptr
访问基类的方式)受保护的析构函数,这是你原来的问题)。
boost::shared_ptr
keeps internally a single pointer. boost::shared_ptr
内部保留一个指针。 When creating boost::shared_ptr
you are passing to its constructor a SINGLE pointer which can be regarded as / converted to pointer to any of those TWO template argument types. 在创建
boost::shared_ptr
您将向其构造函数传递一个SINGLE指针,该指针可被视为/转换为指向任何这两个模板参数类型的指针。
I believe it is because the definition of the boost template declares the sharedpointer a friend of the <Class T> class from your template instantiation. 我相信这是因为boost模板的定义声明了sharedpointer是模板实例化中<Class T>类的朋友。
This is a snipet I copied from the boot shared pointer header file. 这是我从引导共享指针头文件复制的snipet。
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
template<class Y> friend class shared_ptr;
template<class Y> friend class weak_ptr;
#endif
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.