指针和指向类数据成员的指针的抽象

时间:2014-07-11 20:04:30

标签: c++ pointers abstraction

我想很多人都熟悉指向类数据成员的用法。最常见的用法是当您有一个对象列表并使用只知道数据成员的相对偏移量的函数处理它们时。

我有一个嵌套结构,在注册时,我只知道内部结构(b)相对于父结构(A)的相对偏移。全局结构实例(a)尚未实例化。

在程序的某个时刻,将实例化一个,并且所有数据成员(包括子结构(b))将与全局结构的绝对位置绑定。

请参阅下面的示例

struct A {
   int a1;
   int a2;
   struct B {
      int b1;
      int b2;
   }b; 
}

descA.register(&A::a1,"a1");
descA.register(&A::a2,"a2");
descA.register(&A::b,descB);
...
descB.register(&B::b1,"b1");
descB.register(&B::b2,"b2");

A a; // create instance of nested struct

descA.bind(a);

// a1,a2,b requires the base pointer of a
// b1,b2 requires the base pointer of b   

现在,我想抽象一个指针的概念,因为我有一个简单的绝对引用,A*,我有一个指向内部struct B的指针,我想生成{{} 1}}将B*的deference隐藏在指针类中。

更新:

一般来说,经过一些想法后,我需要有三个独立的接口来指向这个指针类。

  1. 我需要能够将val字符串分配给指针指向的位置
  2. 如果基指针尚未设置,我需要设置指针对象的基指针
  3. 我需要定义结构指针的概念,这样我就可以将基指针传播给它的所有成员
  4. 这些将是我需要的具体指针类:

    1. 绝对结构指针 - 全局结构指针
    2. relative struct pointer - struct
    3. 中的struct指针
    4. 相对值指针 - 结构内的值指针
    5. 绝对值指针 - 一个值指针,其中值的位置已知

1 个答案:

答案 0 :(得分:0)

一旦我能够定义这个指针抽象的接口。我能够毫不费力地实现我的需求。

////////////////////////////////////////////////////////////////////////////////
// Pointer abstraction
////////////////////////////////////////////////////////////////////////////////

// interfaces
class Reference {
    public:    
        virtual ~Reference() {}
        virtual void assign(std::string val) = 0;
};

template<typename BT>
class BasePtr {
    public:
        virtual void setBase(BT* ptr) = 0;
        virtual bool isBaseSet() { return false; }
};

template<typename ST>
class StructPtr {
    public:
        virtual void addPtr(BasePtr<ST>* ptr) = 0;
        virtual void notify() = 0;
};

// implementation
template<typename T>
class AbsStructPtr : public Reference, 
                     public BasePtr<T>,
                     public StructPtr<T> {
    public:
        AbsStructPtr() {}
        ~AbsStructPtr() {}
        void assign(std::string val) {
            throw std::runtime_error("struct pointer: cannot assign to struct");
        }
        void setBase(T* p) {
            ptr = p;
        }
        void addPtr(BasePtr<T>* ptr) {
            pointers.push_back(ptr);
        }
        void notify () {
            for(size_t i=0; i<pointers.size(); i++) {
                pointers[i]->setBase(ptr);
            }
        }
    protected:
        T* ptr;
        typedef std::vector<BasePtr<T>*> PointerVec;
        PointerVec  pointers;

};

template<typename T, typename PT>
class RelStructPtr : public Reference, 
                     public BasePtr<PT>,
                     public StructPtr<T> {
    public:
        RelStructPtr(T PT::*ptr) : memptr(ptr), baseptr(NULL) {}
        ~RelStructPtr() {}
        void assign(std::string val) {
            throw std::runtime_error("struct pointer: cannot assign to struct");
        }
        void setBase(PT* p) {
            baseptr = p;
        }
        void addPtr(BasePtr<T>* ptr) {
            pointers.push_back(ptr);
        }
        void notify () {
            T* ptr = &(baseptr->*memptr);
            for(size_t i=0; i<pointers.size(); i++) {
                pointers[i]->setBase(ptr);
            }
        }
    protected:
        T PT::*memptr;
        PT* baseptr;
        typedef std::vector<BasePtr<T>*> PointerVec;
        PointerVec  pointers;
};

template<typename T, typename PT>
class RelValPtr : public Reference, 
                  public BasePtr<PT> {
    public:
        RelValPtr(T PT::*ptr) : memptr(ptr), baseptr(NULL) {}
        ~RelValPtr() {}
        void assign(std::string val) {
            assigner.assign(val);
        }
        void setBase(PT* p) {
            baseptr = p;
        }
    protected:
        T PT::*memptr;
        PT* baseptr;
        Assigner<T> assigner;
};

template<typename T>
class AbsValPtr : public Reference,
                  public BasePtr<T> {
    public:
        AbsValPtr(T* ptr) : valptr(ptr) {}
        ~AbsValPtr() {}
        void assign(std::string val) {
            assigner.assign(val);
        }
        void setBase(T* p) {
            throw std::runtime_error("Base pointer is set");
        }
        bool isBaseSet() { return true; }
    protected:
        T* valptr;
        Assigner<T> assigner;
};