Q:

how an object can obtain a pointer to the class object it belongs to c++

Penelope object will need to access the getKey() method in the GameWorld class (which is the base class for your StudentWorld class), Penelope object (or more likely, one of its base classes)
will need a way to obtain a pointer to the StudentWorld object it belongs to.  If you look at code example, you’ll see how Penelope’s doSomething() method first gets a pointer to its world via a call to
getWorld() (a method in one of its base classes that returns a pointer to a StudentWorld), and then uses this
pointer to call the getKey() method. 
void Penelope::doSomething()
{
    int ch;
    if (getWorld()->getKey(ch))
   {
    // user hit a key during this tick! 
      switch (ch)
   {
       case KEY_PRESS_LEFT:
         ... move Penelope to the left ...;
         break;
      case KEY_PRESS_RIGHT:
        ... move Penelope to the right ...;
        break;
      case KEY_PRESS_SPACE:
         ... add flames in front of Penelope...;
         break;
   // etc…
  }
}
...
}

code for getWorld() is actually required

A:

A minimal example compatible with your question
#include <iostream>

class GameWorld {
  public:
    int getKey(int & k) const { k = 123; }
};

class StudentWorld : public GameWorld {
};

class Student {
  public:
    Student(StudentWorld * w) : world_(w) {}

    StudentWorld * getWorld() const { return world_; }

  private:
    StudentWorld * world_;
};

class Penelope : public Student {
  public:
    Penelope(StudentWorld * w) : Student(w) {}
    void doSomething();
};

void Penelope::doSomething()
{
  int ch;

  getWorld()->getKey(ch);
  std::cout << ch << std::endl;
}

int main()
{
  StudentWorld sw;
  Penelope pe(&sw);

  pe.doSomething();
}

I give/memorize the world through a pointer rather than a reference/weak_ptr because strangely getWorld visibly returns a pointer
I do a direct inheritance between Penelope and the owner of getWorld() even the question says it may not be direct, and I name that owner Student just because seem consistent
In the question Penelope object is strange and must be Penelope's object or Penelope instance because Penelope is a class rather than an instance

New version because of your remark where the Penelope instance is created by StudentWorld but you have to understand like that StudentWorld knows Penelope class and this bad, a fabric or something like that have to be used.  May be StudentWorld known Student to memorize all of their instances but certainly not a child class like Penelope
#include <iostream>

class GameWorld {
  public:
    int getKey(int & k) const { k = 123; }
};

class Penelope;

class StudentWorld : public GameWorld {
  public:
    Penelope * createPenelope();
};

class Student {
  public:
    Student(StudentWorld * w) : world_(w) {}

    StudentWorld * getWorld() const { return world_; } 

  private:
    StudentWorld * world_;
};

class Penelope : public Student {
  public:
    Penelope(StudentWorld * w) : Student(w) {}
    void doSomething();
};

Penelope * StudentWorld::createPenelope()
{
  // probably the instance is not just returned
  // but also memorized to save all the students
  return new Penelope(this);
}

void Penelope::doSomething()
{
  int ch;

  getWorld()->getKey(ch);
  std::cout << ch << std::endl;
}

int main()
{
  StudentWorld sw;
  Penelope * pe = sw.createPenelope();

  pe->doSomething();
}

Compilation and execution :
pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -g w.cc
pi@raspberrypi:/tmp $ ./a.out
123

