как C++ реализует полиморфизм внутренне?

Уважаемый сэр!

я должен сказать Вам что, что я знаю и что я не знаю о заданном вопросе так, чтобы можно было обратиться к слабой области моего понимания.

я знаю, что C++ реализует полиморфизм при помощи Vtable, который является массивом указателей, на которые каждый указатель указывает на виртуальную функцию класса, каждый класс в иерархии имеет vtable. теперь предположите, что у меня есть следующий класс

class person
{
    char name[20];
public:
    person(char* pname)
    {
        strcpy(name,pname);
    }

    virtual void show()
    {
        cout<<"inside person show method, Name: "<<name;
    }
};

class teacher:public person
{
     int scale;

     teacher(char*pname, int s):person(pname)
     {
         scale=s;
     }

     void show()
     {
         cout<<"inside the teacher show method, Scale: "<<scale;
     }
};

теперь предположите, что я пишу в основной программе

person *ptr;
ptr=new teacher(16,"Zia");
ptr->show();

теперь я, путают в этой точке, вызов перейдет к выставочной функции базового класса, теперь поскольку это - виртуальная функция так это, внутренний изгиб вызывает approprite функцию. я знаю, что я неправ здесь. я смущен это, что было бы последовательностью вызовов. Что является ролью Vtable и как это работает, уточните.

7
задан avakar 31 January 2010 в 09:26
поделиться

4 ответа

Я думаю, что вы должны обратить внимание на книгу Стэнли Б. Липпмана » внутри объектной модели C ++ ».

Давайте посмотрим на внутреннюю презентацию для ваших классов:

Виртуальная таблица для человека и учителя

|---------------|  +---> |------------------------|
|  name         |  |     | "type_info" for person |
|---------------|  |     |------------------------|
|__vptr__person |--+     | "person::~person"      |
|---------------|        |------------------------|
person p;                | "person::show"         |
                         |------------------------|

|----------------|  +---> |-------------------------|
|person subobject|  |     | "type_info" for teacher |
|----------------|  |     |-------------------------|
|__vptr__teacher |--+     | "teacher::~teacher"     |
|----------------|        |-------------------------|
teacher t;                | "teacher::show"         |
                          |-------------------------|               

В целом мы не знаем точный тип адресов объекта PTR при каждом вызове Show (). Однако мы знаем, что через PTR мы можем получить доступ к виртуальной таблице, связанной с классом объекта.

Хотя мы не знаем, какой экземпляр Show (), чтобы вызвать, мы знаем, что адрес каждого экземпляра содержится в слоте 2.

Эта информация позволяет компилятору внутренне преобразовывать вызов

( *ptr->vptr[ 2 ] )( ptr ); 

в этом преобразовании. , VPTR представляет собой внутренне генерируемую указатель виртуальной таблицы, вставленный в каждом классном объекте, а 2 представляет собой показывать () назначенный слот в виртуальной таблице, связанной с точкой иерархией. Единственное, что нам нужно сделать во время выполнения, вычисляет динамический тип PTR (и соответствующим VTable) с использованием RTTI.

8
ответ дан 6 December 2019 в 06:50
поделиться

В стандарте ничего не сказано о том, как реализовывать полиморфизм. Один класс один vtbl и один объект один vptr - самый популярный способ. Надеюсь, следующий псевдокод будет полезен.

typedef struct {
    void (*show)(void* self);
    // more

} person_vtbl;

typedef struct {
      person_vtbl* vtbl;
      char         name[20];
} person;

void person_show(void* self) {
      cout<<"inside ... "<<static_cast<person*>(self)->name;
}
// more

static person_vtbl person_vtbl_ = { &person_show }; // vtbl for person class

void person_ctor(void* self, char const* name) {
      person* p = static_cast<person*>(self);
      strcpy(p->name, name);
      p->vtbl   = &person_vtbl  // vptr of person object
}

typedef struct {
    person base;
    int    scale;
} teacher;

void teacher_show(void* self) {
      cout<<"inside the tearch ... "<<static_cast<teacher*>(self)->scale;
}
static person_vtbl teacher_vtbl_ = { &teacher_show };

void teacher_ctor(void* self, char const* name, int s) {
      teacher* t = static_cast<teacher*>(self);
      person_ctor(&t->base, name);     // construct base part
      t->scale   = s;                  // construct teacher part
      t->vtbl    = &teacher_vtbl_;     // vptr of teacher object
}

// construct teacher :
// person* ptr = new teacher("Zia", 16);

teacher* tmp = static_cast<teacher*>( malloc( sizeof *tmp );
teacher_ctor(tmp, "Zia", 16);  // vptr of tmp points to teacher_vtbl_
person* ptr = &tmp->base;

// call virtual function though pointer
// ptr->show()

ptr->vptr->show(ptr); // call teacher_show(ptr);
3
ответ дан 6 December 2019 в 06:50
поделиться
import re
title = re.sub("[\W\d]", "_", title.strip())

должно быть быстрее.

Если вы хотите заменить последовательность смежных букв, не являющихся буквами, одним подчеркиванием, используйте

title = re.sub("[\W\d]+", "_", title.strip())

, что еще быстрее.

Я только что провел сравнение времени:

C:\>python -m timeit -n 100 -s "data=open('test.txt').read().strip()" "''.join(map(lambda x: x if (x.isupper() or x.islower()) else '_', data))"
100 loops, best of 3: 4.51 msec per loop

C:\>python -m timeit -n 100 -s "import re; regex=re.compile('[\W\d]+'); data=open('test.txt').read().strip()" "title=regex.sub('_',data)"
100 loops, best of 3: 2.35 msec per loop

Это также будет работать на Юникод последовательностей (под Python 3, \W соответствует любому символу, который не является символом слова Юникод. В разделе Python 2 необходимо дополнительно установить флаг UNICODE ).

-121--3038725-

Я обычно переключаюсь между режимом Makefile, текстовым режимом и режимом C в зависимости от того, в какой строке я участвую. Если вы хотите лучше, вы должны написать режим!

-121--1309628-

Поскольку show объявлен virtual в классе person , компилятор не будет жестко кодировать вызов метода так, как это было бы сделано для невиртуального метода, он вместо этого скомпилирует поиск в V-таблице, чтобы получить нужную функцию.

Поэтому ptr- > show () будет скомпилирован как ptr- > vtable ['show'] () , что означает «поиск указателя функции, соответствующего методу show , и его выполнение».

Поскольку во время выполнения ptr точек к объекту класса teacher , слот vtable для show содержит указатель на метод show в классе teacher . Именно поэтому выполняется правильный метод.

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

9
ответ дан 6 December 2019 в 06:50
поделиться

Язык C ++ не определяет реализации полиморфизма, даже vtable . Это дело компиляторов.
Одна из возможных реализаций указана Винсентом Робертом .

6
ответ дан 6 December 2019 в 06:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: