使用“->”运算符时保留访问权限

2024-04-16

我有两节课

template<class Type>
class SafePtr {
public:
    SafePtr() {}
    ~SafePtr() {}

    void Lock(Type* data, void* key)
    {
        if (!pKey)
        {
            pKey = key;
            pData = data;
        }
    }

    Type* Unlock(void* key) const
    {
        if (key == pKey)
            return pData;
    }

    Type* operator->() 
    {
        return pData;
    }

private:
    Type* pData = nullptr;
    void* pKey = nullptr;
};

template<class Type>
class SafePtrArray {
public:
    SafePtrArray() {}
    ~SafePtrArray() {}

    template<class... Args>
    SafePtr<Type> CreatePtr(Args&&... args)
    {
        Type* data = new Type(args...);
        ptrs.insert(ptrs.end(), data);

        SafePtr<Type> ptr;
        ptr.Lock(data, this);
        return ptr;
    }

    Type* UnlockPtr(const SafePtr<int>& ptr)
    {
        return ptr.Unlock(this);
    }

    void Destroy(const SafePtr<int>& ptr)
    {
        Type* pointer = ptr.Unlock(this);

        for (auto itr = ptrs.begin(); itr != ptrs.end(); itr++)
        {
            if ((*itr) == pointer)
            {
                delete pointer;
                ptrs.erase(itr);
            }
        }
    }

private:
    std::vector<Type*> ptrs;
};

目标是保护指针,以便用户可以访问其成员,但不能操作其实际指针(主要是过早删除它)。而且我还需要将所有指针存储在一个数组中,以便当父对象销毁时,我可以自动销毁所有分配的指针

为此我使用两个类,SafePtr and SafePtrArray. SafePtrArray创建并存储指针并将它们包装在SafePtr并将其返回给用户。SafePtr只是一个包装器并且不应该让用户可以访问底层指针,但将允许他们访问其成员。

一开始工作正常,但很快我就发现了这个错误,

int main()
{
    SafePtrArray<int> ptr;
    auto pInt = ptr.CreatePtr();
    int* i = pInt.operator->();     // Users can get access to the underlying pointer using this.

    ptr.Destroy(pInt);
}

有没有办法阻止用户访问底层类型并阻止他们在有权访问其成员的同时操作指针?


我仍然认为你试图解决一个问题,该问题更多地与 API/代码、文档的设计中可能存在的缺陷有关,或者与使用它的人缺乏 C++ 知识有关,而“解决方案”是缺点多于优点。

如果 C++ 程序员不知道什么是所有权或不尊重它,并盲目地删除对象或释放指针的内存,那么将会有更大的问题。您可能会将问题转移到代码的不同部分。

话虽如此,现在您可以做的最接近不暴露指针的事情是这样的:

(代码只是概念证明,所以像call可能需要改进)

#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;
}

所以没有针对此类事情的保护措施。

除了显示的代码之外,还有一个建议反射 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0578r1.html该功能现在已完成,可以获取有关类型成员的信息,但这并未添加到 c++20 中,并且有一个用于元类 http://www.open-std.org/Jtc1/sc22/WG21/docs/papers/2018/p0707r3.pdf这也尚未包含在标准中。

有了这两个建议,您也许能够实现一些更好用的东西。但我对其好处的担忧仍然存在。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用“->”运算符时保留访问权限 的相关文章

随机推荐

  • 在 Jade 中使用 HTML 被认为是不好的做法吗?

    Jade 看起来像一个很酷的模板引擎 我想我将在下一个项目中使用它 然而 有些语法对我来说没有意义 这样做你会得到什么 ul li a href book a Book A 代替 ul li a href book a Book A a l
  • 为什么使用互斥量而不是布尔变量进行线程同步?

    我正在尝试了解 C 中的多线程编程 我有疑问 既然我们使用MUTEXES来进行线程同步 为什么我们不能使用布尔变量来阻塞要执行的代码的关键区域 与布尔变量相比 静音变量有何特点 PS 其实这个问题是在采访中问到的 因此 请分享您对此的了解
  • 可用 Wifi 设备列表

    我想显示可用 Wifi 设备的列表 这是我的代码 我不明白这里有什么错误 wifi WifiManager getSystemService Context WIFI SERVICE if wifi isWifiEnabled false
  • 如何向 AWS 根账户 MFA 添加更多设备

    我的 iPhone 中已经安装了 Google 身份验证器 并且正在使用它登录我的 AWS 根账户 我想添加使用我的 Android 手机通过 MFA 登录的功能 并使用相应的令牌生成器 Android 应用程序 是否可以添加第二个设备以及
  • 具有多个参数的 Laravel FindOrNew

    我使用 laravel FindOrNew 来获取具有两个参数的条目 或创建一个新参数 option App Option findOrNew user id gt this gt id option name gt optionName
  • 如何为一般 authError 消息定义 FlashHelper/Component 元素

    将 CakePHP 从 2 6 2 更新到 2 7 2 后 在创建 auth flash 消息时出现丢失密钥错误 如何定义默认的元素模板authError Since SessionComponent setFlash 已经已弃用 http
  • 向量集合上的 C++ iterator_adapter [重复]

    这个问题在这里已经有答案了 可能的重复 展平迭代器 https stackoverflow com questions 3623082 flattening iterator 我有一个某种类型的向量 比如 int 我想迭代一下 在向量中的元
  • 通过 Tweepy 获取 Twitter 中的所有关注者 ID

    是否有可能获得像麦当劳这样拥有超过 100 万粉丝的帐户的完整粉丝列表 我使用 Tweepy 并遵循代码 c tweepy Cursor api followers ids id McDonalds ids for page in c pa
  • 公开应用程序秘密到底有多糟糕?

    经过重大的巫术之后 我终于让分数 API 正常工作了 事实证明你必须设置Enhanced Auth Dialog to disabled或者 Facebook 会忽略您的publish actions允许 只是提醒一下 以防其他人遇到困难
  • 创建 Facebook 应用程序请求

    我试图在特定事件发生时从应用程序向用户发送消息 现在我有这个代码 param array message gt XYZ shared a file with you data gt additiona string data access
  • Linq to SQL 中的动态表名称

    大家好 我有一个可怕的数据库 我必须使用它 而 linq to sql 是我用来检索数据的选项 我试图通过根据用户选择输入不同的表名称来重用函数 但据我所知 无法修改 DataContext 查询中的 TEntity 或 Table 这是我
  • 使用flash动作脚本开发网络游戏

    简而言之 如果我想使用 Flash 技术开发在线游戏 你能告诉我一些很好的学习资源吗 包括3D游戏 您可以从新发布的开始Flash平台游戏技术中心 http www adobe com devnet games 在 Adob e Devne
  • 如何在 ionic 2(搜索栏)中进行自动完成

    我正在尝试在我的搜索栏中自动完成我到目前为止所做的事情 我有一个包含一些字符串的数组 然后我尝试在我的项目中列出我能够搜索的特定项目 但我的要求不是在列表中显示项目 我必须在单击搜索栏时 数组中的所有字符串都应该出现 并且我必须进行搜索
  • 帮助构建 boost asio ssl 示例

    我一直在研究 asio ssl 示例 链接如下 尽管尽了最大努力 我还是无法将 openssl 链接到 boost 示例中 ld 的输出是 ld 缺少 libssl a 中的符号 我无法弄清楚的是 我发现 libssl a 中带有 nm 的
  • cudaMemcpyToSymbol 的问题

    我正在尝试复制到恒定内存 但我不能 因为我对 cudaMemcpyToSymbol 函数的用法有误解 我正在努力追随this http developer download nvidia com compute cuda 4 1 rel t
  • 在 Scala 中是否有更好的方法来提升 PartialFunction?

    我偶尔会遇到以下模式 我基本上有一个PartialFunction SomeType AnotherType 并希望将其视为Function SomeType Option AnotherType eg def f s SomeType O
  • jQuery:有一种方法可以将颜色(色调)应用于图像吗?

    有没有一种方法可以使用 jQ 或某些插件对图像进行着色 应用色调 谢谢 我能想到的最简单的方法是在图像上覆盖一个半透明的 div 一个小例子 HTML div class overlay div img src img jpg CSS ov
  • 使用 ADODB 记录集执行联接更新查询

    在下面的代码中 我想将 ADODB 记录集 rs3 连接到表 tblValueChain10 并根据 ADODB 记录集 rs3 中提取的值更新 3 个不同的列 目前 更新查询未返回任何内容 Dim st Sql3 As String Di
  • Metro IndexedDB,浏览数据库

    我正在尝试使用 IndexedDB 将数据存储在 Windows 8 的 Metro 应用程序中 我希望能够浏览数据库 以监视我的操作是否按预期修改数据 所以我的问题是 有没有办法查看地铁应用程序 IE10 的实际数据库 类似于 Chrom
  • 使用“->”运算符时保留访问权限

    我有两节课 template