通过提供"proxy"指针隐藏原始指针

Hiding raw pointers by providing a "proxy" pointer

本文关键字:指针 隐藏 原始 proxy      更新时间:2023-10-16

是否有一种方法可以将原始指针隐藏在"代理"或"假"指针后面,从而提供对原始指针功能的访问而不显示其地址?

原始指针的管理类如下所示:

template<typename T>
class hidden_ptr
{
public:
    hidden_ptr(T *RawPointer);
    ~hidden_ptr();
    T *get()
    {
       return new proxy_pointer<T>(raw_pointer)
    }
};

然后使用:

class Foo
{
public:
    Foo();
    ~Foo();
    void do_bar();
    void do_bar2();
};
int main()
{
    Foo *raw_pointer = new Foo();
    hidden_ptr<Foo> hidden(raw_pointer);
    Foo *proxy = hidden.get();
    proxy->do_bar();
    proxy->do_bar2();
    delete proxy; //The raw pointer is still safe till the hidden object destructs
}

如果有一种方法,proxy_ptr会是什么样子?

满足目前为止提供的需求组合的唯一方法是使类Foo成为各种双模式类:它应该能够充当主(隐藏)对象,以及自身的公共代理,即另一个Foo对象。

一个相当"丑陋"的实现可能如下所示

class Foo
{
    Foo *redirect_to = nullptr;
    Foo(Foo *redirect_to) : redirect_to(redirect_to) { ... }
public:
    Foo() { ... }
    ~Foo() { ... }
    Foo *get_proxy() { return new(this); }
    void do_bar() {
      if (redirect_to) {
        return redirect_to->do_bar();
      ...
    }
    void do_bar2() {
      if (redirect_to) {
        return redirect_to->do_bar2();
      ...
    }
    ...
};

之后,您将能够创建和删除代理访问通过Foo *指针。是否将这些代理包装成任何类型的智能指针取决于您—这不是重点。

int main()
{
    Foo *raw_pointer = new Foo();
    Foo *proxy = raw_pointer->get_proxy();
    proxy->do_bar();
    proxy->do_bar2();
    delete proxy;
}

同样,如果您愿意,您可以将hidden_ptr添加到混合物中。

仔细看一下上面的代码就会发现,通过一个pimpl风格的实现可以更优雅地实现它,其中所有对象都成为指向隐藏实现类的代理。但似乎你不喜欢这种方法的原因(到目前为止我还没有弄清楚)。

有两个:std::unique_ptrstd::shared_ptr。尽管它们背后的一般意图更多地是为了提供简单的资源管理,但它们满足了您的请求。

是。这很简单。只需将指针成员设置为私有,然后重载*和->操作符来解引用该私有成员。但这也是一件毫无意义的事情,一个"中国盒子"编程的极端情况,你创建的"抽象"实际上只是其他数据类型的别名或包装。

你可以这样做:

#include <iostream>
template<typename T>
class hidden_ptr
{
public:
    hidden_ptr() = delete;
    hidden_ptr(hidden_ptr const&) = delete;
    hidden_ptr(T data) : ptr_(new T{data}) {}
    void operator=(hidden_ptr const&) = delete;
    ~hidden_ptr() {delete ptr_;}
    T* operator->() {return ptr_;};
    void reset(T data) {this->~hidden_ptr(); ptr_ = new T{data};}
    void set(T value) {*ptr_ = value;}
    T get() {return *ptr_;}
private:
    T* ptr_;
};
class A
{
public:
    void print() {std::cout << "A::print" << std::endl;}    
};
int main() 
{
    hidden_ptr<int> ptr_int(5);
    hidden_ptr<A> ptr_a(A{});
    ptr_int.reset(10);
    std::cout << ptr_int.get() << std::endl;
    ptr_a->print(); 
}

这样用户不能访问指针地址。这是你想要的吗?