Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Вопрос по С++  (Прочитано 31624 раз)
0 Пользователей и 10 Гостей смотрят эту тему.
annarv
Гость
« : 20-08-2005 06:49 » 

Я недавно начала изучать С++. К сожалению в книге разобраны основные темы, но поверхностно. Так что прошу помочь.
Почему чисто виртуальный деструктор нужно объявлять protected в базовом классе, а потом реализацию деструктора описавать не в производном классе а как глобальную функцию.Для чего это может быть нужно.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 20-08-2005 06:59 » 

Э.. А можно узнать литературу по которой ты учишся, и цитату того места, где об этом сказано.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 20-08-2005 11:37 » 

Чистый виртуальный деструктор не "нужно" но МОЖНО (видимо) объявить защищенным.
Я сам никогда не сталкивался с подобным применением, но возможно это вопросы из разряда множественного защищенного наследования. Литературы под рукой нет Жаль
По поводу реализации в виде глобальной функции - тоже совсем не обязательно. Если только для каких-то м.б. конкретных хитростей реализации? Типа убрать вместе с экземпляром класса еще чего-нибудь (глобальное)?
Вот уж действительно интересно - откуда такие хитрые хитрости берутся? Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 20-08-2005 13:11 » 

Цитата
а потом реализацию деструктора описавать не в производном классе а как глобальную функцию.

Цитата
По поводу реализации в виде глобальной функции - тоже совсем не обязательно.
Я конечнго в этом деле совсем новичек и до Finch'a с Михалычем мне далеко, но объясните мне, как можно описывать реализацию метода класса глобально. Или я чего-то не допонял или под глобальностью имелось ввиду что-то типа этого
Код:
class cl
{
private:
int i;
public:
cl(){i=0;}
~cl();
}
cl::~cl() //Это что-ли глобальная реализация?
{
cout << "Good buy";
}
« Последнее редактирование: 20-12-2007 19:17 от Алексей1153++ » Записан

ещё один вопрос ...
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 20-08-2005 15:17 » 


Код:
class cl
{
private:
int i;
public:
cl(){i=0;}
~cl();
}
cl::~cl() //Это что-ли глобальная реализация?
{
cout << "Good buy";
}

Да нет, это обычная реализация. Просто есть еще inline , когда реализация метода описывается "в теле" описания класса.
Я, честно говоря, имел в виду (и думал) в смысле использования в деструкторе некой глобальной функции... М.б. к самому классу имеющей не самое непосредственное отношение.
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
Vadim Mc
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 20-08-2005 15:27 » 

Good bye - это вообще показывает что вызывается обычный стандартный деструктор и всего - который срабатывает при выходе из программы или какой либо метода (функции класса)
cl () {i=0;} конструктор инициализируется значением переменной i=0
По чем учите коллега, я тоже новичек но у Джеса либерти звучит все именно так
« Последнее редактирование: 20-08-2005 15:32 от NL » Записан

"Теория теорией, но сточки зрения инженера-практика никакая, даже самая элегантная методология, предлагаемая учеными, не стоит и ломаного гроша, если она не помогает в построении реальных, работающих систем." @ Гради Буч
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 20-08-2005 15:35 » 

Господа, и дамы! Улыбаюсь
Будьте внимательнее и конкретнее, пожалуйста, в вопросах и ответах.
to annarv
ну что вам стоило точнее задать вопрос и процитировать источник? Все бы упростилось Улыбаюсь
to NL
"...звучит все именно так" Как? Как у annrv или как у NL? Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 20-08-2005 15:48 » new

Цитата
По чем учите коллега, я тоже новичек но у Джеса либерти звучит все именно так
Я читал Г. Шилдта. А пример на скорую руку из головы вынул, случайно так получилось.  А как книга называется по которой ты учишь? Книга русская? и каково мнение о ней? А то может тоже просмотрю. Вообще сколько книг не читай, в каждой что-то новое для себя найдешь.
Записан

ещё один вопрос ...
Vadim Mc
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 20-08-2005 15:49 » 

Сама формулировка
lass cl
{
private:
int i; // закрытый член класса, тип - целый
public:
cl(){i=0;} // Конструктор, про содании i присваивается 0
~cl(); //Стандартный деструктор
}
cl::~cl() //Это что-ли глобальная реализация? //Это Реализация стандартного деструктора -
{
cout << "Good buy"; - //Индикатор того, что произошел вызов деструктора, такие же вещи можно писать и в реслизации конструктора или конструктора копий
}
Вот именн это и хотел сказать - источник Джесс Либерти, Освой С++ за 21 день (я щас заканчиваю день 10)
Записан

"Теория теорией, но сточки зрения инженера-практика никакая, даже самая элегантная методология, предлагаемая учеными, не стоит и ломаного гроша, если она не помогает в построении реальных, работающих систем." @ Гради Буч
Vadim Mc
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 20-08-2005 15:52 » 

Цитата
По чем учите коллега, я тоже новичек но у Джеса либерти звучит все именно так
Я читал Г. Шилдта. А пример на скорую руку из головы вынул, случайно так получилось. А как книга называется по которой ты учишь? Книга русская? и каково мнение о ней? А то может тоже просмотрю. Вообще сколько книг не читай, в каждой что-то новое для себя найдешь.
====================================================================================
Я выбирал исходя из того, что институт закончил давно.
Книга эта есть на главной странице сайта  в виде файла dvj на русском
Для начинающего (ИМХО) в самый раз
Хотя как известно - практика критерий истины
« Последнее редактирование: 20-08-2005 15:55 от NL » Записан

"Теория теорией, но сточки зрения инженера-практика никакая, даже самая элегантная методология, предлагаемая учеными, не стоит и ломаного гроша, если она не помогает в построении реальных, работающих систем." @ Гради Буч
annarv
Гость
« Ответ #10 : 20-08-2005 17:20 » 

В книге(Шилдт) этого как раз таки нет. Это меня на экзамене озадачили вопросом, для чего может быть нужен защищенный деструктор. Поэтому хотелось на будущее выяснить.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #11 : 20-08-2005 17:28 » 

Единственное, что я вижу, чтобы не убить случайно объект при реализации например паттерна програмирования Singleton. Тогда надо делать стат функцию, которая будет уже вызывать зашишенный деструктор и попутно обнулять стат переменные объекта.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 20-08-2005 17:32 » 

Да, про защищенный деструктор там кажется нет. Я так понимаю, если делать защищенным, значит это как-то связано с наследованием. Надо от этого копать.
annarv, а у тебя препод не приколист, а то может там ответ подошел бы типа "НЕ ДЛЯ ЧЕГО" Улыбаюсь.
Finch, не видел твой последний пост про паттерны .
« Последнее редактирование: 20-08-2005 17:36 от nikedeforest » Записан

ещё один вопрос ...
Mayk
Гость
« Ответ #13 : 20-08-2005 19:14 » 

Да нет, это обычная реализация. Просто есть еще inline , когда реализация метода описывается "в теле" описания класса.
Небольшая поправка.
Если функция (в данном случае деструктор) описана в теле и объявлена виртуальной(см условие задачи), то она не будет inline.
virtual inline это оксюморон - подстановка inline функции предполагает определенность этой самой ф-ции, а virtual как раз наоборот(никогда неизвестно что вызовется. И вызовется ли что-нибудь вообще). Так что можно смело описывать в теле класса Улыбаюсь

Тогда надо делать стат функцию, которая будет уже вызывать зашишенный деструктор и попутно обнулять стат переменные объекта.
Ну на самом деле нам никто не запрещает обнулить стат переменную из деструктора. Если конечно, объект не размещен статически. Но даже тогда вызoв деструкторa посреди работы программы выглядит весьма странной идеей(гораздо логичнее сделать ф-цию reset()).
Кроме того, обычно Singleton'ы наследуются закрыто(чтобы наследуесый класс нельзя было привести к типу Singleton), поэтому он вполне может иметь открытый доступ.

Я так понимаю, если делать защищенным, значит это как-то связано с наследованием.
Идея! Например мы можем объявить класс для вывода графических примитивов на экран:
Код:
class Graphics{
    public:
    virtual line(Point p1, Point p2, int color)=0;
    static Graphics* instance();
};
И реализовать его в файлах типа graphics_opengl.cpp:
Код:
static class Graphics_OpenGL : Graphics
{
    static Graphics_OpenGL ogl;
    void line(...){glBegin(...);... }
    Graphics* instance(){return &ogl};
    ~Graphics();
};
И через directx. А потом выбирать на этапе линковки что мы хотим использовать - directx или opengl.
Наличие деструктора в реализации opengl уничтожит всё связаное с opengl. наличие деструктора в Graphics уничтожит всё, что создал сам Graphics.
А так как деструктор защищён, то клиент не сможет просто так сделать delete Graphics::instance();, что  может быть довольно не желательно.

PS. оффтоп(учу шаблоны) - в данном случае класс Graphics является шаблоном проектирования proxy? или чем-то другим?
« Последнее редактирование: 20-12-2007 19:19 от Алексей1153++ » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #14 : 20-08-2005 19:22 » 

Mayk, если например еше поставить счетчик вызовов конструктора и уменьшать его при вызове деструктора, то деструктор нельзя вызывать напрямую. Иначе объект будет убит. Хотя его счетчик еше не обнулен.
В принципе почти все объекты ядра работают по такому принципу. Пока кто то использует объект, он сушествует.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 21-08-2005 04:26 » 

Да нет, это обычная реализация. Просто есть еще inline , когда реализация метода описывается "в теле" описания класса.
Небольшая поправка.
Если функция (в данном случае деструктор) описана в теле и объявлена виртуальной(см условие задачи), то она не будет inline.
virtual inline это оксюморон - подстановка inline функции предполагает определенность этой самой ф-ции, а virtual как раз наоборот(никогда неизвестно что вызовется. И вызовется ли что-нибудь вообще). Так что можно смело описывать в теле класса Улыбаюсь
Небольшая поправка на небольшую поправку Улыбаюсь Улыбаюсь
Ответ был дан на конкретный приведенный пример Улыбаюсь А там этим "оксюмороном" и не пахнет. А в контексте условия задачи - конечно же она не будет inline.
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
annarv
Гость
« Ответ #16 : 21-08-2005 07:40 » 

Скажите существует ли деструктор по умолчанию(то есть если мы не задаем его сами)? Ведь при выходе из программы объект по любому удаляеться.
Судя по написанному ранее, защищенный деструктор нужен для того чтобы не удалить объект, но если деструктор по умолчанию находиться в public,то объект все равно будет удален при выходе из блока?

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

class Base{
char *p;
public:
Base(char *c);
virtual void f();
protected:
virtual ~Base()=0;
};

Base::~Base(){delete p;}

class Derived:public Base{
public:
void f();
};

main(){
Base *pBase;
Derived ob1("Str1"),ob2("Str2");
{
pBase= &ob1;
pBase->f()
}
pBase=&ob2;
pBase->f();
}

Записан
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 21-08-2005 12:14 » 

Видимо слегка подытоживая сказанное выше, можно сказать, что защищенный деструктор может быть нужен для:
1. Защищенный деструктор допускает доступ только из производных классов. Это можно применять, например, для того, чтобы предотвратить создание объектов базовых классов "напрямую", но обеспечив создание из них производных классов.
2. Или для того, чтобы ни у кого не было соблазна удалить объект явно самому.
3. Как один из вариантов деструктор также можно сделать защищенным, чтобы исключить возможность удаления объекта оператором delete.
И видимо еще для кучи всякого Улыбаюсь
А деструктор по умолчанию, так же как и конструктор - есть Улыбаюсь
Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 22-08-2005 09:16 » 

Пример не компилируется, так как для класса Derived по умолчанию генерируются только два конструктора: Derived() и Derived(const Derived&)
Комплятор не сможет привести аргументы типа char[] к const Derived& и не скомпилирует пример.
Если пример немного доделать, например так
Код:
#include <iostream>
#include <string.h>

using namespace std;

class Base{
    char *p;
public:
    Base(char *c) { p = new char[strlen(c)+1]; strcpy(p, c); cout << "Base( " << p << ")" << endl; }
    virtual void f() {cout << "Base::f()" << endl; }
protected:
    virtual ~Base()=0;
};

Base::~Base(){delete p; cout << "~Base()" << endl;}

class Derived:public Base{
public:
    Derived(char *c) : Base(c) { cout << "Derived( " << c << ")" << endl; }
    void f() {cout << "Derived::f()" << endl;}
};

main(){
    Base *pBase;
    Derived ob1("str1");
    {
        Derived ob2("str2");
        pBase= &ob2;
        pBase->f();
    }
    pBase=&ob1;
    pBase->f();
}

то получится вот что:
Base( str1)
Derived( str1)
Base( str2)
Derived( str2)
Derived::f()
~Base()
Derived::f()
~Base()

Деструктор базового класса будет вызываться при уничтожении объектов классов-наследников.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
DaN(DR)
Гость
« Ответ #19 : 08-11-2005 09:34 » 

Здравствуйте!
Я совсем новичок и у меня возникли такие вопросы: 1) Как сделать проверку на введенные символы(я имею ввиду, что у меня в программе надо ввести число, и мне надо выкинуть сообщ. об ошибке и попросить ещё раз ввести число если ввели, например, букву)?  2) Как реализовать такой вариант - "Press Esc to quit or any key to retry"?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #20 : 08-11-2005 16:54 » 

1. Делаеш проверку введенного символа на диапазон от символа '0' до '9'.
код можно записать так:
Код:
char ch='A';
while (!((ch<='9') && (ch >= '0'))) scanf("%c", ch);
2. Проверяеш ввод на число 27 это ASCII код кнопки ESC
Код:
if (ch == 27)  ........;
else .......;
« Последнее редактирование: 04-12-2007 17:21 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
DaN(DR)
Гость
« Ответ #21 : 08-11-2005 17:32 » 

Thanxxx! Круто!
Только что значит "%c"?
« Последнее редактирование: 08-11-2005 18:26 от DaN(DR) » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #22 : 08-11-2005 20:47 » 

Говориш компу, что ты хочеш считать один символ. Маленькая поправка: надо писать scanf("%c", &ch);
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
DaN(DR)
Гость
« Ответ #23 : 11-11-2005 08:14 » 

А как в С++ называется команда, которая считывает один символ с клавиатуры (аналог Readkey в Pascal'е)?
« Последнее редактирование: 04-12-2007 17:31 от Алексей1153++ » Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 11-11-2005 09:33 » 

Нажатие клавиши можно считать при помощи функции getch, объявленной в заголовочном файле conio.h
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
NetRaider
Гость
« Ответ #25 : 16-11-2005 18:03 » 


virtual inline это оксюморон - подстановка inline функции предполагает определенность этой самой ф-ции, а virtual как раз наоборот(никогда неизвестно что вызовется. И вызовется ли что-нибудь вообще). Так что можно смело описывать в теле класса Улыбаюсь


Виртуальную функцию всегда можно вызвать как 'обычную', невиртуальную функцию. В этом случае 'virtual inline' имеет смысл.


Цитата
Ну на самом деле нам никто не запрещает обнулить стат переменную из деструктора. Если конечно, объект не размещен статически.

Что значит 'объект не размещен статически' ? Деструктор(при том или ином способе удаления) будет вызван в любом случае, независимо от способа удаления объекта.
Цитата
Код:
class Graphics{
 public:
 virtual line(Point p1, Point p2, int color)=0;
 static Graphics* instance();
};
И реализовать его в файлах типа graphics_opengl.cpp:
Код:
static class Graphics_OpenGL : Graphics
{
 static Graphics_OpenGL ogl;
 void line(...){glBegin(...);... }
 Graphics* instance(){return &ogl};
 ~Graphics();
};

Ключевое слово 'static' при определении класса Graphics_OpenGL не применимо (3.7.1/3-4).

Цитата
Наличие деструктора в реализации opengl уничтожит всё связаное с opengl. наличие деструктора в Graphics уничтожит всё, что создал сам Graphics.

0. Здесь нет ни одного деструктора, которые могут что-либо удалять(уничтожать).
1. явное определение деструктора в классе Graphic отсутствует.
2. деструктор будет создан неявно компилятором, и он не при каких условиях не будет виртуальным(это к тому, что не будет происходить вызов деструктора производного класса).
3. объявление деструктора  '~Graphics()' в определении класса Graphics_OpenGL не является законным. Так нельзя. Имя деструктора должно совпадать с именем класса.

4. каким образом можно 'выбирать на этапе линковки что мы хотим использовать - directx или opengl' ? Это я совершенно не понял. (Производные классы с виртуальными функциями изначально рассчитаны на приблизительно такой подход:
  Graphics* p = new Graphics_OpenGL();

Как в данном случае можно 'выбирать на этапе линковки что мы хотим использовать'?. Реализацию Graphics_OpenGL можно подменить классом Graphics_DirectX, но тогда зачем для Graphics_OpenGL применяется имено такое имя класса ? )

Цитата
« Последнее редактирование: 04-12-2007 17:27 от Алексей1153++ » Записан
DaN(DR)
Гость
« Ответ #26 : 27-11-2005 20:42 » 

Помогите, у меня в программе - не выполняется (как я хочу, конечно) такой кусок кода:

...
while (!(ch=27))
{
     ...
      ch=getch();
}
 
Я хочу, чтобы программа выходила только при нажатии Esc, а у меня выходит, даже не спрашивая кнопки, а если условие цикла изменить на while (ch=27) - то, наоборот, не выходит из цикла, чтобы я не нажал (вкл. Esc). В чём дело?  Вот такой я вот
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #27 : 27-11-2005 20:56 » 

Код:
while (!(ch=27))
{
     ...
      ch=getch();
}
Не помню по счету какие это грабли. Но если ты запишеш заместо ch=27, так ch==27. То должно начать работать. Улыбаюсь
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Михалыч
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 28-11-2005 02:19 » 

Этим "граблям" пора присваивать почетное звание "самых популярных граблей" Улыбаюсь Улыбаюсь
И приделать к ним парадную резиновую ручку, чтобы не так больно било Улыбаюсь
Этому быди посвящены отдельные обсуждения, и даже не одно Улыбаюсь
В поиск, господа с граблями! Улыбаюсь Не ленитесь, пожалуйста, сначала самостоятельно поискать решение, а уж потом караул кричать...
« Последнее редактирование: 28-11-2005 02:21 от Михалыч » Записан

Поживем - увидим... Доживем - узнаем... Выживу - учту  Улыбаюсь
DaN(DR)
Гость
« Ответ #29 : 28-11-2005 05:56 » 

Я на этих граблях около часа потратил Улыбаюсь Самое смешное в том, что если бы не ответ, то ещё вопрос - нашел бы я решение. Никак не думал, что ошибка именно там...Никак не могу привыкнуть.
P.S. Сомневаюсь, что резиновая ручка смягчит удар, но по крайней мере хоть один плюс: никто не украл эти грабли.  Улыбаюсь

Кстати, а в С++ можно объявить типом переменной - множество?
« Последнее редактирование: 28-11-2005 07:53 от DaN(DR) » Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines