1

Я видел этот код онлайн, и мне было интересно, как оно реализовано. Поскольку указатели функций-членов не могут быть назначены указателям на функции-члены базового класса, мне любопытно, где хранятся указатели на функции-члены производного класса и как.Наследование функций указателей функций

Это заголовочный файл с тестовыми декларациях

#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 

И это реализация функции, которая добавляет функции-члены какой-то список

// 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; 
} 

мне было интересно, какие данные тип функции-члена хранятся, поскольку они не могут быть сохранены в любом типе указателя функции, известном базовому классу. Также место, где они хранятся, должно будет знать тип класса, в котором они определены, так как любой объект, который называет их e объектам необходимо будет «связать» эти функции с объектами этого типа слишком правильно? В частности, в этой функции, как будет TestCaller знать, как вызвать функции-члены, которые были добавлены к нему?

+0

@ n.m. Но их нужно где-то хранить? – Curious

+0

Базовый класс не задействован, TestSuite есть. – kfsone

+0

Извините, я думаю, что не понимаю, о чем вы спрашиваете. Функции-члены не «хранятся» нигде, они просто есть. Указатели функций функций хранятся в их soecialized типах данных. Это примитивные типы данных без какой-либо структуры. –

ответ

4

Я думаю, что TestCaller имеет конструктор, который выглядит как

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

Обратите внимание, что:

  1. В теле этого конструктора (то есть, когда он конкретизируется), тип Callee известен.

  2. TestCaller сам должен хранить test_method таким образом, что «не знает» Callee, так как он сам не шаблонный класс параметризовано Callee (а на самом деле, может быть больше, чем один Callee).

Так что это классический случай для типа стирания. Это много библиотек (например, boost::TypeErasure или boost::any).

Идея состоит в том, что TestCaller магазины (возможно, косвенно) указывают на базовый класс без шаблонов. Существуют шаблонные версии производного класса. Внутри этого шаблона ctor создается производный класс, и объект этого типа динамически распределяется. Что хранится, но является указателем на базовый класс без шаблона.

+0

Это замечательно! Почему я не подумал об этом раньше. – Curious

+0

@ Curious :-) Я был очень счастлив, когда впервые увидел эту технику (в некоторой библиотеке сериализации). –

+0

Но в коде оператор 'new' вызывается без аргумента шаблона. Так это действительно работает? – Curious

Смежные вопросы