【问题标题】:Pointers to a class within itself in C++Pointers to a class within itself in C++
【发布时间】:2022-05-09 20:39:18
【问题描述】:

I am analyzing some codes in c++ and I came across this configuration.

class jack {
  //rest of the class body here
  public:
    jack *a;
};

What is the theory of using a pointer in that configuration?

【问题讨论】:

  • What do you mean by what is the theory? That pointer could point to an instance of jack. Why someone would need that is impossible to answer without more information.
  • It works because at the time you declare the pointer inside the class/struct, you do not need the complete type, you only need to know the name. There is probably some fancy name for this that somebody else will point out.

标签: c++


【解决方案1】:

There's no special theory here.

It's allowed to declare pointers to incomplete types, including the type that is under declaration. Because a pointer inside class jack points to class jack it doesn't have to mean that the pointer is to the same object.

This is because there's actually no need for the compiler to know anything more about the target type of a pointer since the pointer is basically just an address. It's first when you're doing certain things with the pointer it need to be a complete type (for example at the point where you dereference it, accesses a member or method, do pointer arithmetics etc).

Allowing this is required in order to allow for constructing a wide range of data structures including linked lists, trees and so on. In C it's also useful since it allows data hiding by not exposing the contents of a struct outside the compilation unit (data hiding is done by just forward declaring the struct in a header and having the complete definition in a C file implementing the API for the struct).

【讨论】:

    【解决方案2】:

    A class containing a pointer to itself is useful in many scenarios.

    But, before I bring forward those scenarios, the fact needs to be understood that:

    just theDefinition of a Class:

    class jack {
    //rest of the class body here
     public:
      jack *a;
    };
    

    does not mean to have any existence unless anObject:

    jack obj;
    

    of that class is created.

    So what this actually means is that when an Object obj of a Class jack is created, it will have, within it, a pointer a which can potentially point to another object of the same class.

    Now, this could be useful if:

    • A chain of objects needs to be created see Linked Lists.

    • An object could be associated to another object of the same type. For example: EveryEmployeecould have aManager, where the Manager himself is also an Employee:

       class Employee {
       //rest of the class body here
        public:
         Employee *manager;
       }
      

    and objects could have relation like:

        Employee salesManager;
        Employee salesWorker;
        salesWorker.manager = &salesManager;
    
    • And you will come across many others whilst working whith different problems.

    【讨论】:

      【解决方案3】:

      So an object of jack can point to another object of that class. Remember this is a pointer to self in an object, so for sure no one needs an extra pointer to self. Say you create two objects

      jack jack1;
      jack jack2;
      jack1.a = &jack2;
      jack2.a = &jack1;
      

      Now the objects are aware of each other. So you don't need a higher level container to manage them. This is the main reason for using pointers to the same class or structure. In this example, jack1 can tell jack2 you are supposed to do something. Then jack2 can do its thing and then ask jack1 to do something else. If you didn't use this approach, you had to keep a list of pointers/objects and then iterator over that to access and communicate with your objects. You can do all sort of complicated stuff with that mechanism, from creating linked lists to FSMs.

      【讨论】:

        【解决方案4】:

        Typical for linked lists. A link list is a concept where you build a list where the first element points to the second element which points to the third element and so on. The last element doesn't point to anything, i.e. the pointer equals nullptr. The entry to the list is typically a pointer (head) which points to the first element (or nullptr if the list is empty).

        // First element
        jack* head = new jack();
        head->a = nullptr;
        
        // Second element
        head->a = new jack();
        head->a->a = nullptr;
        
        //More general - insert element
        jack* newElement= new jack();
        newElement->a = nullptr;
        if (head == nullptr)
        {
            head = newElement;
        }
        else
        {
            jack* tmp = head;
            while(tmp->a != nullptr)  // iterate the list to find last element
            {
                tmp = tmp->a;
            }
            tmp->a = newElement; 
        }
        
        // Remember to clean up when done
        while (head != nullptr)
        {
            jack* tmp = head;
            head = head-> a;
            delete tmp;
        }
        

        But use the std containers (vector, list, etc) instead of writing your own.

        【讨论】:

          猜你喜欢
          • 2022-12-02
          • 1970-01-01
          • 2022-11-20
          • 2022-12-02
          • 2022-12-01
          • 1970-01-01
          • 2022-12-28
          • 2022-12-26
          • 1970-01-01
          相关资源
          最近更新 更多