Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 004. Подсчёт ссылок и свой умный указатель

Войти
Регистрация
Восстановить пароль
Рейтинг: 1.00. Голосов: 1.

Пишу игровой движок на C++. 004. Подсчёт ссылок и свой умный указатель

Запись от 532235 размещена 04.11.2017 в 02:45

Нужно создать общий класс для всех. Самый общий.

Новый файл в папке include - gtBaseObject.h - добавить в gost.h ниже #include <gtTypes.h>

Содержимое
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
#pragma once
#ifndef __GT_BASE_OBJECT_H__
#define __GT_BASE_OBJECT_H__
 
/*
    Общий класс.
*/
 
namespace gost{
 
    //  Все объекты движка наследуют его через gtRefObject
    class gtBaseObject{
    protected:
 
        //  ненужно создавать объект вручную
        gtBaseObject( void ){}
 
    public:
 
        virtual ~gtBaseObject( void ){}
 
        //  первая виртуальная функция в vtable
        //  апплодисменты тому кто узнает откуда идея
        virtual void special_fix_for_playstation( void ){}
    };
 
}
 
#endif
Теперь нужно сделать подсчёт ссылок

Новый файл в папке include - gtRefObject.h - добавить в gost.h ниже #include <gtBaseObject.h>

Содержимое
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
#pragma once
#ifndef __GT_REF_OBJECT_H__
#define __GT_REF_OBJECT_H__
 
/*
    Подсчёт ссылок
*/
 
namespace gost{
 
    //  Все объекты наследуют этот класс.
    class gtRefObject : public gtBaseObject{
    
        //  счётчик
        mutable u32 m_count;
    
    public:
 
        //  конструктор
        gtRefObject( void ) : m_count( 1U ){}
 
        //  деструктор
        virtual ~gtRefObject( void ){}
 
        //  получить количество ссылающихся на этот объект
        u32 GetReferenceCount( void ) const {
            return m_count;
        }
 
        //  Когда ещё 1 объект получает адрес, вызывается эта функция
        //  Просто означает что адрес этого объект а есть ещё у кого-то
        //  Нужно учитывать это создавая новые производные классы
        //  И не нужно забывать про Release()
        void AddRef( void ) const {
            ++m_count;
        }
 
        //  В конструкторе как видно, счётчик инициализируется значением 1
        //  Когда вызывается Release, счётчик уменьшается на 1
        //  Если счётчик равен 0 то происходит удаление объекта
        void Release( void ) const {
            --m_count;
            if( !m_count ){
                delete this;
            }
        }
    };
 
}
 
#endif
и теперь простенькая обёртка к указателю

Новый файл в папке include - gtPtr.h - добавить в gost.h ниже #include <#include <gtRefObject.h>

Содержимое
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
#pragma once
#ifndef __GT_PTR_H__
#define __GT_PTR_H__
 
/*
    Враппер для указателя
*/
 
namespace gost{
 
    //  Его нужно использовать только в связке с gtPtr
    template <typename Type>
    class gtPtrNew{
 
        Type * m_pointer;
    
    protected:
        gtPtrNew( void ) : m_pointer( nullptr ) {}
 
    public:
 
        gtPtrNew( Type* o ) : m_pointer( o ){}
 
        Type*   Data( void ) const {
            return m_pointer;
        }
    };
 
    //  Простая оболочка к указателю
    template <typename Type>
    class gtPtr{
    
        Type * m_pointer;
 
    public:
    
        gtPtr( void ) : m_pointer( nullptr) {}
 
        //  добавит указатель с типом имеющим метод AddRef
        gtPtr( const gtPtr& ptr ){
            if( ptr.m_pointer ){
                ptr.m_pointer->AddRef();
            }
            m_pointer = ptr.m_pointer;
        }
    
        //  ненужно делать так gtPtr<чтото> (new gtИмя);
        //  для создания новых объектов есть gtPtrNew
        gtPtr( Type* object ){
            if( object ){
                object->AddRef();
            }
            m_pointer = object;
        }
 
        //  просто передаёт указатель, не вызывая AddRef
        gtPtr( const gtPtrNew<Type>& ptr ){
            m_pointer = ptr.Data();
        }
 
        //  автоматическое удаление
        ~gtPtr(){
            if( m_pointer ){
                m_pointer->Release();
            }
            m_pointer = nullptr;
        }
 
        Type* operator->() const {
            return m_pointer;
        }
 
        void operator=( Type* e ) {
            if( e ){
                e->AddRef();
            }
            if( m_pointer ){
                m_pointer->Release();
            }
            m_pointer = e;
        }
 
        void operator=( const gtPtrNew<Type>& rp ){
            if( m_pointer ){
                m_pointer->Release();
            }
            m_pointer = rp.Data();
        }
 
        void operator=( const gtPtr& rp ){
            if( rp.m_pointer ){
                rp.m_pointer->AddRef();
            }
            if( m_pointer ){
                m_pointer->Release();
            }
            m_pointer = rp.m_pointer;
        }
 
        Type* Data( void ) const {
            return m_pointer;
        }
    
    };
 
}
 
#endif
Тест

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class BASE : public gtRefObject{
public:
    ~BASE(){ printf("Destroy base\n"); }
 
};
 
class CHILD : public BASE{
public:
    ~CHILD(){ printf("Destroy child\n"); }
};
 
...
 
{       
    gtPtr<BASE> obj(gtPtrNew<BASE>(new CHILD));
    gtPtr<BASE> obj2(gtPtrNew<BASE>(new CHILD));
    gtPtr<BASE> obj3(gtPtrNew<BASE>(new CHILD));
}
Размещено в Игровой движок
Просмотров 322 Комментарии 5
Всего комментариев 5

Комментарии

  1. Старый комментарий
    Аватар для Новичок
    А разве delete this можно писать?
    Запись от Новичок размещена 10.11.2017 в 23:52 Новичок вне форума
  2. Старый комментарий
    Аватар для Новичок

    delete this

    А разве delete this можно писать?
    Запись от Новичок размещена 10.11.2017 в 23:52 Новичок вне форума
  3. Старый комментарий
    Аватар для Avazart
    Цитата:
    delete this
    А разве delete this можно писать?
    Можно и в данном скорее всего, в конкретно данном коде ничего за это не будет... (по крайней мере пока не придется изменять код)

    А вот само решение когда на сам объект возложена ф-ция "владения самим собой" мне кажется спорным.
    Спрашивается зачем изобретать такие велосипеды, можно было возложить удаление на смарт поинтеры?


    (хотя глядя на весь код точнее будет сказать что ф-ция владения(и подсчета ссылок) размазана по нескольким классам, вместо того что бы концентрироваться в умном указателе)
    Запись от Avazart размещена 11.11.2017 в 00:20 Avazart вне форума
    Обновил(-а) Avazart 11.11.2017 в 00:56
  4. Старый комментарий
    Аватар для 532235
    я даже не удивлён. код - почти копия высокопрофессионального кода из очень дорогого ПО мирового уровня (не ваш отечественный зашквар).

    всегда найдётся умник который увидит изъян. Всё равно где.

    лишь бы был.



    -
    чтоб умники не выскакивали, включил заслон
    Запись от 532235 размещена 11.11.2017 в 02:48 532235 вне форума
  5. Старый комментарий
    Аватар для 532235
    Цитата:
    Сообщение от Avazart Просмотреть комментарий
    .

    насмешил
    я думаю всё очевидно.
    Запись от 532235 размещена 11.11.2017 в 15:00 532235 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru