Curious
Curious

Reputation: 21510

Inheriting member function pointers

I saw this code online and I was wondering how it is implemented. Since member function pointers cannot be assigned to a base class's member function pointers I am curious where the pointers for the derived class's member functions are being stored and how.

This is the header file with the test declarations

#ifndef TestStudent_h
#define TestStudent_h

#include <iostream>
#include <string>

// Note 1
#include "TestCase.h"
#include "TestSuite.h"
#include "TestCaller.h"
#include "TestRunner.h"

#include "Student.h"

class StudentTestCase : public TestCase { // Note 2 
public:
  // constructor - Note 3
  StudentTestCase(std::string name) : TestCase(name) {}

  // method to test the constructor
  void testConstructor();

  // method to test the assigning and retrieval of grades
  void testAssignAndRetrieveGrades();

  // method to create a suite of tests
  static Test *suite ();
};
#endif

And this is the implementation of the function that adds the member functions to some sort of list

// method to create a suite of tests - Note 7
Test *StudentTestCase::suite () {
  TestSuite *testSuite = new TestSuite ("StudentTestCase");

  // add the tests
  testSuite->addTest (new TestCaller  
      ("testConstructor", &StudentTestCase::testConstructor));
  testSuite->addTest (new TestCaller  
      ("testAssignAndRetrieveGrades", 
       &StudentTestCase::testAssignAndRetrieveGrades));
  return testSuite;
}

I was wondering what data type the member functions are being stored in since they cannot be stored in any function pointer type known to the base class.. Also the location where they are stored will have to know the type of the class under which these are defined since whatever entity that calls these objects will need to "link" these functions with objects of that type too right? Specifically in this function how will TestCaller know how to call the member functions that were added to it?

Upvotes: 1

Views: 65

Answers (1)

Ami Tavory
Ami Tavory

Reputation: 76297

My guess is that TestCaller has a constructor that looks like

template<class Callee>
TestCaller(
    const std::string &description, 
    void (Callee::*test_method)());

Note that:

  1. Within the body of this constructor (i.e., when it is instantiated), the type of Callee is known.

  2. TestCaller itself must store test_method in a way that does not "know" Callee, since it is not itself a template class parameterized by Callee (and in fact, there might be more than a single Callee).

So this is a classic case for type erasure. There are many libraries that do this (e.g., boost::TypeErasure or boost::any).

The idea is that TestCaller stores (probably indirectly) pointers to a non-template base class. There are templated versions of a derived class. Within this templated ctor, the derived class is instantiated, and an object of this type is dynamically allocated. What is stored, though is a pointer to the non-template base class.

Upvotes: 4

Related Questions