有没有办法阻止指针的分配?

时间:2017-04-03 15:02:22

标签: c++

一个棘手的问题。如果想编写一个将指针返回给某个IFoo对象的函数,是否可以阻止指定该指针? 我不想让IFoo成为单例,我可以隐藏或删除复制和赋值运算符,但C ++实际上是否允许使用模式,我明确地必须调用其他人来获取对象?

背景问题是:我正在考虑某种依赖容器,你应该总是要求容器得到一些IFoo *(为了多态而指针)。用户永远不能将其保存到某个局部变量或成员,以避免对其进行停顿引用。 (对于指示容器不再返回Foo的情况,该情况源自IFooBar

编辑以澄清,尽管用户R Sahu已经说过这是不可能的。 事实上,马克B的例子是我想要阻止的完美例证:

IFoo* foo_ptr_I_will_keep_forever = obj->getIFoo();

当我没有接口但只有显式的类型实例时,我可以返回一个引用,给定一个私有操作符=和copy ctor就足够了。

3 个答案:

答案 0 :(得分:2)

给他们一个对象(他们可以存储,如果他们想要的话)总是通过私人(朋友)接口查找真实对象。

例如,IFooCaller通过获取当前IFoo并转发所有呼叫来实现IFoo

答案 1 :(得分:2)

你的标题是:

  

有没有办法阻止指针的分配?

不,如果函数返回指针,则无法阻止。

但是,如果返回一个句柄,该句柄可以是指向仅向前声明的类型的指针,也可以是可用于显示真实对象的整数值,并确保所有实际功能都适用于处理,然后你可以有更多的自由,当你可以删除真实对象,而没有留下客户端代码悬挂指针的风险。

这是一个演示概念的简单程序。

#include <iostream>
#include <set>

// Foo.h

struct Foo;
using FooHandle = Foo*;

FooHandle createFoo();

void fooFunction1(FooHandle h);

void fooFunction2(FooHandle h);

// Test Program

int main()
{
   FooHandle h = createFoo();
   fooFunction1(h);
   fooFunction2(h);
   fooFunction1(h);
   return 0;
}

// Foo implementation.

namespace FooImpl
{
   std::set<Foo*>& getLiveFooObjects()
   {
      static std::set<Foo*> liveObjects;
      return liveObjects;
   }

   bool isValid(Foo* h)
   {
      return (getLiveFooObjects().find(h) != getLiveFooObjects().end());
   }
}

using namespace FooImpl;

struct Foo {};

FooHandle createFoo()
{
   FooHandle h = new Foo{};
   getLiveFooObjects().insert(h);
   return h;
}

void fooFunction1(FooHandle h)
{
   if ( isValid(h) )
   {
      std::cout << "In fooFunction1.\n";
   }
   else
   {
      std::cout << "Ooops. The handle is no longer valid.\n";
   }
}

void fooFunction2(FooHandle h)
{
   std::cout << "In fooFunction2.\n";
   delete h;
   getLiveFooObjects().erase(h);
}

输出:

In fooFunction1.
In fooFunction2.
Ooops. The handle is no longer valid.

答案 2 :(得分:1)

一个中间答案,可以防止意外存储指向特定实现的指针,但不会阻止某人故意这样做:

template <typename T> class service_wrapper;

class service_manager
{
    template <typename T> friend class service_wrapper;

public:
    template <typename T>
    service_wrapper<T> get() const;

private:
    template <typename T>
    T* get_instance() const;
};

template <typename T>
class service_wrapper
{
    friend class service_manager;

public:
    T* operator->() const;

private:
    service_wrapper(service_manager const & p_sm) : sm(p_sm) { }
    service_manager const & sm;
};

template <typename T>
T* service_wrapper<T>::operator->() const
{
    return sm.get_instance<T>();
}

您的经理只会分发service_wrapper<T>的实例。 operator->实现允许使用wrapper->method(...);调用服务,并始终从服务管理器获取实现指针。

这可以像:

一样被规避
T *ptr = sm.get<T>().operator->();

但这不是你不小心做的事情。