Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176

Почему при создании класса у абстракных классов по иерархии пусто в _vptr ?

07.06.2015, 19:28. Показов 1304. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот что я имею ввиду:
Миниатюры
Почему при создании класса у абстракных классов по иерархии пусто в _vptr ?  
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.06.2015, 19:28
Ответы с готовыми решениями:

Виртуальные функции при создании иерархии классов
#include "stdafx.h" #include <iostream> using namespace std; class var{ int temperatura; float shirina; public: virtual...

Торможение UI при хитрой иерархии классов
Всем привет! Извините за много букв, заранее спасибо всем, кто прочитал! Подскажите, пожалуйста, что может быть причиной такого...

Реализация иерархии классов на основе класса "Грузоперевозчик"
Помогите, пожалуйста!!!!Четвёртый день сижу над этой задачей и ничего не получается. Создать базовый класс «Грузоперевозчик» и...

12
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
07.06.2015, 20:22
Цитата Сообщение от Doublench Посмотреть сообщение
Вот что я имею ввиду
А кода в текстовой форме скинуть не хочется для демонстрации проблемы?
Цитата Сообщение от Doublench Посмотреть сообщение
при создании класса у абстракных классов
Экземпляр абстрактного класса создать нельзя.
0
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176
07.06.2015, 20:27  [ТС]
Tulosba, А что вам кинуть та ? Код большой
Экземпляр абстрактного класса создать нельзя.
а почему тогда у других классов всё в порядке с _vptr ? Они тоже наследуются от двух абстрактных классов.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
07.06.2015, 20:33
Цитата Сообщение от Doublench Посмотреть сообщение
А что вам кинуть та ? Код большой
Подготовь минимально достаточный пример, в котором проявляется описанная тобой ситуация.
Цитата Сообщение от Doublench Посмотреть сообщение
а почему тогда у других классов всё в порядке с _vptr ?
Опять таки, на основании минимального примера покажи различие в поведении.
Тогда можно будет более предметно говорить о чем-то.
0
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176
07.06.2015, 20:39  [ТС]
Tulosba,
Строго по иерархии ниже:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma once
 
/*
 * Базовый класс для всех контейнеров
 */
 
#include <cstring>
#include "MemoryManager.h"
 
/*
 * Базовый класс для всех абстрактных контейнеров
 */
class Container {
protected:
    MemoryManager &_memory;
 
public:
    /*
     * Базовый класс для исключений, которые запускает контейнер
     */
    struct Error {
        char msg[256];
 
        //Error(const char *err_msg) { strcpy(msg, err_msg); }
    };
 
    class Iterator {
    public:
        /*
         * Возврашает явно указатель на элемент, на который указывает итератор в
         * данный момент.
         * Неявно возвращает размер данных
         */
        virtual void *getElement(size_t &size) = 0;
 
        /*
         * Возвращает true, если есть следующий элемент, иначе false.
         */
        virtual bool hasNext() = 0;
 
        /*
         * Переход к следующему элементу.
         */
        virtual void goToNext() = 0;
 
        /*
         * Проверка на равенство итераторов.
         */
        virtual bool equals(Iterator *right) = 0;
    };
 
    Container(MemoryManager &mem) : _memory(mem) { }
 
    /*
     * Функция возвращает значение, равное количеству элементов в контейнере.
     */
    virtual int size() = 0;
 
    /*
     * Функция возвращает значение, равное максимальной вместимости контейнера в
     * байтах.
     */
    virtual size_t max_bytes() = 0;
 
    /*
     * Функция возвращает указатель на итератор, указывающий на первый найденный в
     * контейнере элемент. Если элемент не найден, возвращается пустой указатель.
     */
    virtual Iterator *find(void *elem, size_t size) = 0;
 
    /*
     * Удаление всех элементов из контейнера.
     */
    virtual void clear() = 0;
 
    /*
     * Создание итератора, соответствующего данному типу контейнера.
     */
    virtual Iterator *newIterator() = 0;
 
    /*
     * Функция возвращает указатель на итератор, указывающий на первый элемент
     * контейнера. Если контейнер пустой, возвращается нулевой указатель.
     */
    virtual Iterator *begin() = 0;
 
    /*
     * Функция возвращает указатель на итератор, указывающий позицию за последним
     * элементом контейнера. Если контейнер пустой, возвращается нулевой
     * указатель.
     */
    virtual Iterator *end() = 0;
 
    /*
     * Eсли контейнер пуст возвращает true, иначе false
     */
    virtual bool empty() = 0;
 
    /*
     * Удаление элемента из позиции, на которую указывает итератор iter.
     * После удаления итератор указывает на следующий за удаленным элемент.
     */
    virtual void remove(Iterator *iter) = 0;
};


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
#pragma once
 
#include "Container.h"
 
/*
 * Базовый класс для некоторой группы абстрактных контейнеров.
 */
class GroupContainer : public Container {
public:
    GroupContainer(MemoryManager &mem) : Container(mem) { }
};


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
 
#include <stddef.h>
 
/*
 * Базовый класс менеджера памяти
 */
 
class MemoryManager {
private:
    size_t _size;
 
public:
    MemoryManager(size_t sz) : _size(sz) { }
 
public:
    size_t size() { return _size; }
 
    virtual void *allocMem(size_t sz) = 0;
 
    virtual void freeMem(void *ptr) = 0;
};


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#pragma once
 
#include "GroupContainer.h"
#include "MemoryManager.h"
 
/*
 * Абстрактный класс: дерево
 */
class AbstractTree : public GroupContainer {
public:
    class Iterator : public Container::Iterator {
    public:
        /*
         * Переход к родительской вершине. Возвращает false если текущая вершина -
         * корень или end().
         */
        virtual bool goToParent() = 0;
 
        /*
         * Переход к дочерней вершине № child_index. Возвращает false если дочерней
         * вершины с таким номером нет.
         */
        virtual bool goToChild(int child_index) = 0;
    };
 
    /*
     * конструктор
     */
    AbstractTree(MemoryManager &mem) : GroupContainer(mem) { }
 
    /*
     * деструктор
     */
    virtual ~AbstractTree() { }
 
    /*
     * Добавление элемента как дочернюю вершину № child_index вершины, на которую
     * указывает итератор. В случае успешного добавления функция возвращает
     * значение 0, в случае неудачи 1.
     */
    virtual int insert(Iterator *iter, int child_index, void *elem,
                       size_t size) = 0;
 
    /*
     * Удаление вершины, на которую указывает итератор. Если leaf_only==1 и
     * вершина не является листом, возвращает false
     * !!! Примечание: метод remove удаляет вершину вместе со всеми ее потомками
     */
    virtual bool remove(Iterator *iter, int leaf_only) = 0;
};


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#pragma once
 
#include "Tree.h"
 
enum color {
    RED, BLACK
};
 
/*
 * Класс узел
 */
#pragma pack(push, 1)
class Node {
    int *data;
    color color_;
    Node *left;
    Node *right;
    Node *parrent;
 
public:
    Node(int *data)
            : left(NULL), right(NULL), parrent(NULL), color_(RED), data(data) { };
 
    ~Node() {};
 
public:
    friend class RBtree;
};
#pragma pop
 
/*
 * Класс дерево
 */
class RBtree : public AbstractTree {
public:
    /*
     * Класс итератор дерева
     */
    class Iterator : public AbstractTree::Iterator {
        RBtree *Rbtree;
 
    public:
        Node *cur;
 
    public:
        Iterator(Node *n, RBtree *rb) : cur(n), Rbtree(rb) { };
 
        ~Iterator() { };
 
        /*
         * Виртуальные функции
         */
    public:
        // Container
        void *getElement(size_t &size);          // done! ok
        bool hasNext();                          // done! ok
        void goToNext();                         // done! ok
        bool equals(Container::Iterator *right); // done! ok
 
        // Tree
        bool goToParent();               // done! ok
        bool goToChild(int child_index); // done! ok
    };
 
private:
    Node *root;
    Node *NIL;
 
public:
    RBtree(MemoryManager &mem);
 
    ~RBtree() { };
 
    /*
     * Пользовательские функции
     */
public:
    void tree_insert(Node *n);
 
    void left_rotate(Node *n);
 
    void right_rotate(Node *n);
 
    void rb_insert(Node *n);
 
    Node *rb_delete(Node *n);
 
    void rb_delete_fixup(Node *n);
 
    Node *tree_successor(Node *n);
 
    Node *tree_predecessor(Node *n);
 
    void inorder_tree_walk(Node *n);
 
    void inorder_tree_walk_count(Node *n, int *count);
 
    void inorder_tree_walk_delete(Node *n);
 
    void inorder_tree_walk_delete_all_nodes(Node *n);
 
    Node *iterative_tree_search(Node *n, int *data);
 
    Node *tree_minimum(Node *n);
 
    Node *tree_maximum(Node *n);
 
    /*
     * Виртуальные функции
     */
public:
    // Container
    int size();                              // done! ok
    size_t max_bytes();                      // done! ok
    Iterator *find(void *elem, size_t size); // done! ok
    void clear();                            // done! ok
    Iterator *newIterator();                 // done! ok
    Iterator *begin();                       // done! ok
    Iterator *end();                         // done! ok
    bool empty();                            // done! ok
    void remove(Container::Iterator *iter);  // done! ok
 
    // Tree
    int insert(AbstractTree::Iterator *iter, int child_index, void *elem,
               size_t size);                                  // done! ok
    bool remove(AbstractTree::Iterator *iter, int leaf_only); // done! ok
};


Пример:
C++
1
2
3
Mem mem(0);
    RBtree tree(mem); // тут всё есть в vptr
    RBtree::Iterator *iter = tree.newIterator(); // а тут в vptr пусто, хотя там 4 вирт. метода
C++
1
2
3
4
5
6
7
8
9
RBtree::Iterator *RBtree::newIterator() {
    Node *tmp = this->root;
    //return new RBtree::Iterator(tmp, this);
    RBtree::Iterator *new_ = static_cast<RBtree::Iterator *>(_memory.allocMem(sizeof(RBtree::Iterator)));
    RBtree::Iterator new__(tmp, this);
    *new_ = new__;
    return new_;
 
}
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
07.06.2015, 20:43
вообще выглядит странно. у вас кстати еще нет виртуальных деструкторов, но да ладно. учитывая что вы химичите с аллокаторами, может быть дело в этом. например выделили память, а сконструировать объект в этой памяти забыли. следующая строчка наводит на такие подозрения:
C++
1
RBtree::Iterator *new_ = static_cast<RBtree::Iterator *>(_memory.allocMem(sizeof(RBtree::Iterator)));
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
07.06.2015, 20:46
Цитата Сообщение от Doublench Посмотреть сообщение
а тут в vptr пусто, хотя там 4 вирт. метода
Это тебе чем-то мешает? Что-то не работает в коде (якобы) из-за этого?
Указатель на таблицу виртуальных функций - штука сугубо внутренная для компилятора.
С чего вообще ты решил его понаблюдать в отладчике?
Цитата Сообщение от Doublench Посмотреть сообщение
Пример:
Минимальный? Достаточный? Не думаю.
0
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176
07.06.2015, 20:51  [ТС]
Tulosba, а вот метод
C++
1
2
3
4
5
6
7
8
9
10
11
12
RBtree::Iterator *ptr = tree.newIterator();
    for (int i = 0; i < 1000000; i++) {
        //int *data = new int;
        int *data = static_cast<int *>(mem.allocMem(sizeof(int)));
        *data = i;
        ptr = tree.find(data, size); 
        tree.remove(ptr); // Заходя сюда программа завершается с ошибкой!!!!!!!!!!!!!!
        if ((ptr = tree.find(&i, size))->cur !=
            tree.end()->cur) { // find deleted data`s
            cout << "Error!";
        }
    }
C++
1
2
3
4
5
6
7
8
9
10
void RBtree::remove(Container::Iterator *iter) {
    size_t size;
    int *data = static_cast<int *>(iter->getElement(size));
    Node *del = static_cast<RBtree::Iterator *>(iter)->cur;
 
    iter->goToNext();
    //delete del;
    _memory.freeMem(del);
    this->rb_delete(this->iterative_tree_search(this->root, data));
}
Там типы меняются RBtree::Iterator на Container::Iterator. Поэтому у меня программа валится видимо. Т.к. в vptr не пойми что.
Он не может получить элемент итератора, хотя перед входом в метод он есть, но после смены типа, он не может его прочесть. Вот в этому проблема.
И ещё, до подключения аллокатора, всё исправно работало, но таблицу vptr я не проверял и тогда.
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
07.06.2015, 20:54
попрбуйте плейсмент new добавить:
C++
1
2
3
4
5
6
7
8
9
RBtree::Iterator *RBtree::newIterator() {
    Node *tmp = this->root;
    //return new RBtree::Iterator(tmp, this);
    RBtree::Iterator *new_ = static_cast<RBtree::Iterator *>(_memory.allocMem(sizeof(RBtree::Iterator)));
    new (new_) RBtree::Iterator(tmp, this); // инициализируем объект в выделенной памяти
    //RBtree::Iterator new__(tmp, this);
    //*new_ = new__;
    return new_;
}
0
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176
07.06.2015, 21:36  [ТС]
Perfilov, а что вы тут сделали я не совсем понял ? Это помогло, теперь все верно, но теперь другая функция портит vptr, там придется сделать так же как и тут, как я понял.
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
07.06.2015, 21:49
Лучший ответ Сообщение было отмечено Doublench как решение

Решение

да, везде. ищите инфу по ключевым словам: placement new, размещающий new.
кратко:
создание динамического объекта из двух шагов состоит
1. выделить под объект память.
2. инициализировать (сконструировать) его в этой памяти.

в плюсах первый шаг можно кастомизировать, что вы и сделали. второй - нет.
инициализация - это вот указание правильных значений всяким там vptr, вызов конструкторов внутренних
подобъектов и т.п.

в случае с placement new выделение памяти пропускается. объект конструируется в куске памяти, на начало
которого указывает переданный параметр.

ну и синтаксис у него такой:
new (pointerToMemoryBlock) YourType();

Добавлено через 5 минут
ну и еще для объектов, которые сконструированы таким макаром нужно явно вызывать деструктор:
obj->~ObjectType();
если просто возвращать память в ваш менеджер, может возникнуть утечка. например если у Object есть мембер
std::string - точно будет утечка, т.к. деструкторы этого и других мемберов не позовутся.
1
1 / 1 / 0
Регистрация: 05.07.2013
Сообщений: 176
07.06.2015, 21:52  [ТС]
Perfilov, то есть просто присвоив я ни черта не проинициализировал ? И надо только таким способом ?
0
265 / 165 / 56
Регистрация: 25.02.2015
Сообщений: 435
07.06.2015, 22:49
выходит что так. самодельное управление памятью - хитрая штука.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.06.2015, 22:49
Помогаю со студенческими работами здесь

Почему при виртуальном наследовании компилятор не знает о иерархии?
Рассмотрим пример: class Base { virtual void foo()=0; }; class Derv :public Base { foo(){}

Как при создании экземпляра класса инициализировать переменные вложенного класса
Здравствуйте. Подскажите пожалуйста как при создании екземпляра класа инициализировать переменные вложеного класа. Добавлено через 22...

Использование объекта одного класса при создании нового класса
Добрый вечер. У меня такая проблема. Есть готовый класс L2 - список, на его основе нужно создать дек. Я поступил так: в приватной части...

Вызов другого класса при создании свойства класса
Здравствуйте! Пишу внутри класса, но не в методе: public $ln = DB::getLang(); DB - это другой класс, getLang() - метод в нём. То есть...

Почему при создании веб-страницы в FrontPage автоматически создается папка с изображениями, а при создании веб-страницы в DreamWeaver - нет?
Если я создаю веб-страницу в FrontPage и называю ее, например, page.html, то автоматически создается папка page.files, где хранятся все...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru