Форум программистов, компьютерный форум CyberForum.ru

Можно ли удалить объект экземпляра класса из самого себя? - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ Найти количество чисел в массиве типа char http://www.cyberforum.ru/cpp-beginners/thread1303976.html
задание полностью стоит следующее: в массиве типа char вывести только те слова, которые состоят из латинских букв и вывести количество чисел в массиве, если такие имеются. Числе, не цифр! #include<iostream> #include<string.h> #include <stdlib.h> using namespace std; int main() { char text;//ñòðîêà
C++ Удалить элементы главной диагонали Удалить элементы главной диагонали Почему не работает? for (i=0; i<n; i++) for (j=0; j<m-1; j++) if (i=j) for (i=j; i<n-1; i++) mas=mas; cout<<"our array\n"; http://www.cyberforum.ru/cpp-beginners/thread1303975.html
Создание, просмотр и удаление элементов списка, организованного по принципу LIFO C++
Что делать? Программа просит идентификатор true, false. #include "stdafx.h" #include <iostream> #include <process.h> #include <conio.h> using namespace std; //визначення перелічуваного типу користувача boolean enum boolean(true, false); //визначення шаблону елемента списку за допомогою типу struct struct stack{
Обработка двумерного массива: найти количество строк и номер столбца по условию C++
#include <iostream> #include <iomanip> using namespace std; const int N=20; const int M=20; int main() { double a;
C++ Подскажите.Как вывести N-ую строку или столбец из матрицы? http://www.cyberforum.ru/cpp-beginners/thread1303921.html
Подскажите.Как вывести N-ую строку или столбец из матрицы?
C++ Ошибка "stack around the variable 'n' was corrupted." Есть такая программа. Натуральные числа от 0 до n(a0-an) Необходимо найту сумму всех чисел кратных 5. Выдает ошибку stack around the variable 'n' was corrupted. Почему? #include <clocale> #include <cstdio> int main(){ setlocale(LC_ALL, "Russian"); int n, a, sum=0; printf("введите n"); подробнее

Показать сообщение отдельно
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
23.11.2014, 13:20     Можно ли удалить объект экземпляра класса из самого себя?
Спёрто из книги Дональд Бокс - Сущность технологии COM (крышка 2)
Даже несмотря на то, что открытые операторы над типами данных подняты до уровня чисто виртуальных функций в классе интерфейса, клиент не может приписывать значения объектам FastString, не имея определения класса для класса реализации. При демонстрации клиенту определения класса реализации от него будет скрыта двоичная инкапсуляция интерфейса; что не позволит клиенту использовать класс интерфейса. Одним из разумных способов обеспечить клиенту возможность использовать объекты FastString является экспорт из DLL глобальной функции, которая будет вызывать новый оператор от имени клиента. При условии, что эта подпрограмма экспортируется с опцией extern "С" , она будет доступна для любого транслятора C++.


C++
1
2
3
4
5
6
7
8
9
10
11
// ifaststring.h 
class IFastString { 
  public: 
    virtual int Length(void) const = 0; 
    virtual int Find(const char *psz) const = 0; 
};
 
extern "C" IFastString *CreateFastString(const char *psz); 
      // faststring.cpp (part of DLL)
IFastString *CreateFastString (const char *psz) 
  { return new FastString(psz); }
Как было в случае класса-дескриптора, новый оператор вызывается исключительно внутри DLL FastString, а это означает, что размер и расположение объекта будут установлены с использованием того же транслятора, который транслировал все методы реализации.
Последнее препятствие, которое предстоит преодолеть, относится к уничтожению объекта. Следующая клиентская программа пройдет трансляцию, но результаты будут непредсказуемыми:
C++
1
2
3
4
5
6
7
int f(void)
{
    IFastString *pfs = CreateFastString("Deface me"); 
    int n = pfs->Find("ace me"); 
    delete pfs; 
    return n; 
}
Непредсказуемое поведение вызвано тем фактом, что деструктор класса интерфейса не является виртуальным. Это означает, что вызов оператора delete не сможет динамически найти последний порожденный деструктор и рекурсивно уничтожит объект ближайшего внешнего типа по отношению к базовому типу. Поскольку деструктор FastString никогда не вызывается, в данном примере из буфера исчезнет строка "Deface me", которая должна там присутствовать.


Очевидное решение этой проблемы — сделать деструктор виртуальным в классе интерфейса. К сожалению, это нарушит независимость класса интерфейса от транслятора, так как положение виртуального деструктора в таблице vtbl может изменяться от транслятора к транслятору. Одним из конструктивных решений этой проблемы является добавление к интерфейсу явного метода Delete как еще одной чисто виртуальной функции, чтобы заставить производный класс уничтожать самого себя в своей реализации этого метода. В результате этого будет выполнен нужный деструктор. Модифицированная версия заголовочного файла интерфейса выглядит так:
C++
1
2
3
4
5
6
7
8
9
// ifaststring.h
class IFastString { 
  public: 
    virtual void Delete(void) = 0; 
    virtual int Length(void) const = 0; 
    virtual int Find(const char *psz) const = 0;
};
 
extern "C" IFastString *CreateFastString (const char *psz);
она влечет за собой соответствующее определение класса реализации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// faststring.h
#include "ifaststring.h" 
class FastString : public IFastString { 
    const int m_cch; 
      // count of characters 
      // счетчик символов 
    char *m_psz; 
  public: 
    FastString(const char *psz); 
    ~FastString(void); 
    void Delete(void); 
      // deletes this instance 
      // уничтожает этот экземпляр 
    int Length(void) const; 
      // returns # of characters 
      // возвращает число символов 
    int Find(const char *psz) const; 
      // returns offset 
      // возвращает смещение 
};
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
// faststring.cpp
#include <string.h> 
#include "faststring.h" 
 
IFastString* CreateFastString (const char *psz) { 
    return new FastString(psz);
} 
 
FastString::FastString(const char *psz) : m_cch(strlen(psz)), m_psz(new char[m_cch + 1]) {
    strcpy(m_psz, psz); 
} 
 
void FastString::Delete(void) { 
    delete this; 
} 
 
FastString::~FastString(void) { 
    delete[] m_psz; 
} 
 
int FastString::Lengtn(void) const { 
    return m_cch; 
} 
 
int FastString::Find(const char *psz) const { 
    // O(1) lookup code deleted for clarity 
    // код поиска 0(1) уничтожен для ясности 
}

Рисунок 1.7 показывает представление FastString на этапе выполнения.
Чтобы использовать тип данных FastString, клиентам надо просто включить в программу файл определения интерфейса и вызвать CreateFastString:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include "ifaststring.h"
 
int f (void)
{
    int n = -1 ;
    IFastString * pfs = CreateFastString ("Hi Bob!") ;
    if ( pfs ) {
        n = pfs->Find("ob") ;
        pfs->Delete () ;
    }
    return n ;
}
Можно ли удалить объект экземпляра класса из самого себя?

Отметим, что все, кроме одной, точки входа в DLL FastString являются виртуальными функциями. Виртуальные функции класса интерфейса всегда вызываются косвенно, через указатель функции, хранящийся в таблице vtbl, избавляя клиента от необходимости указывать их символические имена на этапе разработки. Это означает, что методы интерфейса защищены от различий в коррекции символических имен на разных трансляторах. Единственная точка входа, которая явно компонуется по имени, — это CreateFastString — глобальная функция, которая обеспечивает клиенту доступ в мир FastString. Заметим, однако, что эта функция была экспортирована с опцией extern "С", которая подавляет коррекцию символов. Следовательно, все трансляторы C++ ожидают, что импортируемая библиотека и DLL экспортируют один и тот же идентификатор. Полезным результатом этой методики является то, что вы можете спокойно извлечь класс из DLL, использующей одну среду C++, а обратиться к этому классу из любой другой среды C++. Эта возможность необходима при построении основы для независимых от разработчика компонентов повторного пользования.
 
Текущее время: 02:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru