C++ 使用'时保留访问权限-&燃气轮机';操作人员

C++ 使用'时保留访问权限-&燃气轮机';操作人员,c++,pointers,access-protection,C++,Pointers,Access Protection,我有两门课 模板 安全等级{ 公众: SafePtr(){} ~SafePtr(){} 无效锁(类型*数据,无效*键) { 如果(!pKey) { pKey=key; pData=数据; } } 类型*解锁(无效*钥匙)常数 { if(key==pKey) 返回pData; } 类型*运算符->() { 返回pData; } 私人: 类型*pData=nullptr; void*pKey=nullptr; }; 模板 阶级安全{ 公众: safeptraray(){} ~SafePtrArray

我有两门课

模板
安全等级{
公众:
SafePtr(){}
~SafePtr(){}
无效锁(类型*数据,无效*键)
{
如果(!pKey)
{
pKey=key;
pData=数据;
}
}
类型*解锁(无效*钥匙)常数
{
if(key==pKey)
返回pData;
}
类型*运算符->()
{
返回pData;
}
私人:
类型*pData=nullptr;
void*pKey=nullptr;
};
模板
阶级安全{
公众:
safeptraray(){}
~SafePtrArray(){}
模板
SafePtr CreatePtr(Args&&…Args)
{
类型*数据=新类型(参数…);
插入(ptrs.end(),数据);
SafePtr-ptr;
ptr.锁(数据,本);
返回ptr;
}
类型*解锁ptr(常数安全ptr和ptr)
{
返回ptr.Unlock(本次);
}
无效销毁(const SafePtr&ptr)
{
类型*指针=ptr.Unlock(本);
对于(自动itr=ptrs.begin();itr!=ptrs.end();itr++)
{
如果((*itr)=指针)
{
删除指针;
ptrs.擦除(itr);
}
}
}
私人:
std::载体ptrs;
};
说明:
目标是保护指针,以便用户可以访问其成员,但不能操作其实际指针(主要是过早删除)。我还需要将所有指针存储在一个数组中,这样当父对象销毁时,我可以自动销毁所有分配的指针
为此,我使用了两个类,
SafePtr
safeptraray
safeptraray
创建并存储指针,并将其包装在
SafePtr
中,然后将其返回给用户
SafePtr
只是一个包装器,不应让用户访问底层指针,而是允许用户访问其成员

刚开始还可以,但很快我就发现了这个错误

intmain()
{
安全射线;
auto pInt=ptr.CreatePtr();
int*i=pInt.operator->();//用户可以使用此命令访问底层指针。
ptr.销毁(品脱);
}
所以我的问题是,

有没有办法阻止用户访问底层类型,防止他们在有权访问其成员时操纵指针?

我仍然认为您试图解决的问题更多地与API/代码、文档设计中可能存在的缺陷有关,或者用C++的知识,缺少一个使用它的“解决方案”,它比PROs有更多的缺点。 <>如果C++程序员不知道所有权是什么,或者不尊重它,盲目删除对象或者释放指针的内存,那么将会有更大的关注点。您可能会将问题转移到代码的另一部分

话虽如此,您现在能做的最接近于不暴露指针的事情如下:

(代码只是概念的证明,因此,
call
之类的东西可能需要改进)

#包括
#包括
结构测试{
voidfoo(intx,inty,std::stringstr){
标准::cout
有没有办法防止用户访问底层类型,并防止他们在拥有访问其成员的权限时操纵指针

在某些情况下,这是不可能的。如果基础
类型
为a,则提供对第一个非静态非位字段数据成员的访问会破坏您的目标。(注意:仅提供对成员的值的访问是另一回事。)该成员的地址可以通过转换为指向底层对象的指针,从而允许对该指针调用
delete
。“允许”是指调用在语法上是有效的。对于“允许”来说,没有太多其他问题,因为我们正进入未定义的行为

对于非标准布局的类,可能有特定于编译器的(不可移植的)方法来实现相同的效果(将数据成员的地址转换为指向底层对象的指针)。编译器没有理由积极尝试阻止这些事情


如果程序员决定调用未定义的行为,你几乎无法阻止它。

为什么不使用好的旧
shared_ptr
和它的朋友,让你的用户拥有熟悉的界面?你不能用通用的方式来做。你需要它的原因是什么?对于stdlib和其他库中的任何类型,用户都需要lly可以访问对象(及其指针),但不能删除这些对象,因为它们对这些对象没有所有权?(对于
std::shared_ptr
std::unique_ptr
您可以调用
get()
,对于
std::vector()
您可以调用
data()
,对于
std::list
您可以检索元素的指针,…)@D-RAJ用户仍然可以执行
SafePtrArray ptr;delete&ptr;
-这当然是未定义的行为-但是删除您不拥有的对象也会导致未定义的行为(由于对已删除对象的双重释放或访问)。听起来你要么想确保不懂该语言的用户不会做错任何事,要么想绕过代码或文档中可能存在的设计缺陷。如果
操作符->
基本上提供了对指针的访问,我认为你的解决方案是停止认为任何合理的用户都会得到当他们明显不是他们的角色,并且把任何一个会做傻事的用户都注销的时候,即使你管理了一些可怕的黑客来实现你想要的行为,它仍然是C++;他们有直接的内存访问,他们可以做可怕的非标准的东西来访问那个指针,如果你想要的话,你的任务是让你很难做错事。意外,是我
#include <iostream>
#include <string>

struct Test {
  void foo(int x, int y, std::string str) {
    std::cout << x << " " << y << " " << str << std::endl;
  }

  double test = 0.5;
};

template <typename T>
struct Ptr {

  template <auto M, typename... Args>
  auto call(Args... args) {
    return (obj.*M)(std::forward<Args>(args)...);
  }

  template <auto M>
  auto get() { 
    return (obj.*M);
  }

protected:
  T obj;
};

int main() {
  Ptr<Test> p;

  p.call<&Test::foo>(1, 2, "hello");
  std::cout << p.get<&Test::test>() << std::endl;

  return 0;
}
int main() {
  Ptr<Test> p;
  
  delete &p;

  return 0;
}
template<typename T>
struct Ptr {
protected:
    T *obj;
}

template<typename T>
struct Ptr2 {
public:
    T *obj;
};

int main()
{
    Ptr<Test> p;
    Ptr2<Test> *p2 = reinterpret_cast<Ptr2<Test>*>(&p);
    
    std::cout << p2->obj << std::endl;
}