Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструкторы и потоки 
V
    Опции темы
yorgan
Дата 10.6.2008, 17:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 5.6.2008

Репутация: нет
Всего: нет



Подскажите плиз ссылку на хорошую статью, где подробно описано все по конструкторам (по умолчанию, с параметрами, копирования, способы вызова конструкторов, еще какие-нибудь "тонкие" места) и по потокам.
Если кто-то обладает достаточными теоретическими знаниями и не прочь сам написать мануал, буду только очень благодарен!
Заранее спасибо!
PM MAIL   Вверх
Rififi
Дата 10.6.2008, 17:58 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1254
Регистрация: 9.3.2008

Репутация: 3
Всего: 36



PM MAIL   Вверх
bsa
Дата 10.6.2008, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



yorgan, а что именно у тебя вызывает затруднение?
С конструкторами все очень просто. Они вызываются при создании объекта класса. Бывает конструктор по умолчанию. Это конструктор, у которого не указываются параметры. Есть конструктор копирования - он принимает ссылку на объект того же класса. Все конструкторы с одним параметром (в т.ч. и копирования) имеют интересную особенность, они могут вызываться, если в месте инициализации объекту присваивается что-то, для чего есть конструктор или что может быть неявно преобразовано к тому, для чего есть конструктор. Чтобы это не происходило, существует ключевое слово explicit. Примеры:
Код
class MyClass
{
public:
    MyClass() {} //это конструктор по умолчанию
    MyClass(const MyClass &obj); //это конструктор копирования, он не меняет объект, на который ссылается obj
    MyClass(int x); //это конструктор с одним параметром типа int
    explicit MyClass(const char *str); //это конструктор с одним параметром типа "указатель на строку"
};

...

MyClass c1; //ok - вызовется конструктор по умолчанию
MyClass c2(c1), c3 = c1; //в обоих случаях вызовется конструктор копирования
MyClass c4 = 15; //вызовется конструктор с параметром типа int
MyClass c5 = "asdfg"; //ошибка - нельзя таким образом вызывать explicit конструктор
MyClass C6("asdfg"); //ok - вызовется конструктор с параметром типа const char *

PM   Вверх
rrrFer
Дата 10.6.2008, 19:12 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.5.2008
Где: Красноярск

Репутация: 0
Всего: 1



yorgan
если под потоком имеется ввиду процесс то вот - присоединяю файл(там очень вкратце написано)
если же под потоками имеются ввиду вообще потоки, то можно прочитать в книжке Павловской "программироание на языке высокого уровня"  -гугли. Там написано крайне просто и понятно.
Вообще поток можно видеть как класс с определенными для него функциями. Также поток представляет собой файл, и определенные функции позволяют работать с этим файлом: записывать в него и считывать... Классы потоков имеют конструкторы(как и любой нормальны класс вообще). 
    Для файловых потокв: если поток входной то конструктор ifstream, выходной ofstream, двунаправленный - fstream. еслы вызван конструктор без параметров, то создается обьект, но с файлом он не связывается. параметры этих конструкторов: имя файла char *, и режим открытия файла, второй параметр можно иногда опускать, т.к. по умолчанию для ifstream он определен ios::in, ofstream - ios::out|ios::trunc. режимы открытия описаны в структуре open_mode{}, т.е. trunc, например, удаляет файл если такой файл уже существует, т.е. при использовании ofstream of("out.txt"); если файл out.txt существует, то будет удален и создан заново, также часто используется ios::bynary - т.е. двоичный поток.
    Функции для работы с потоками(некоторые) вот: get() - возвращает символ из потока(код символа), getline(char *buffer, int num) где как можно догадаться buffer - то куда будут записываны считанные символы, num - Их количество. Аналогичная функция read(char *buffer, int num).Разница между read(...) и getlime в том, что getline помещает символ конца строки в buffer. Можно установить позицию для чтения функцией seekg(int position), узнать текущую позицию чтения потока int tellg(). - это были потоки из istream. 
    В ostream есть вот: flush() - переписывает поток на устройство, put(char c) - записывает символ в поток, seekp(int position) - установка позиции записи, tellp() - возвращает текущую позицию, write( char *buffer, int num) - записывает в поток num символов из потока buffer.
а вот маленький примерчик:
Код

#include <fstream>
#include <iostream>
using namespace std;
void main(){
    ofstream f("C:\\file.txt");
    char s[25];
    for(int i=0;i<2;i++){
        cin>>s;
        f.write(s,strlen(s));
    }
    system("pause");
    f.flush();
    system("pause");
    f.close();
    system("pause");
}

загляните в файл до вызова flush() и после - вот так оно работает. Кстати, если выкинуть flush из программы, то содержимое потока все равно перепишется в файл, также можно убрать из программы close() - все ранво закроется, и данные не будут потеряны. Предполагаю что при завершении программы вызывается что то типа fcloseall() только для потоков...

Это сообщение отредактировал(а) rrrFer - 10.6.2008, 19:18

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  ________.7z 7,61 Kb
PM MAIL WWW ICQ   Вверх
yorgan
Дата 11.6.2008, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 5.6.2008

Репутация: нет
Всего: нет



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


bsa, В очередной раз  СПАСИБО!


rrrFer,  "Повловская" у меня есть smile на досуге в метро перед зачетом почитаю. За мануал тоже спасибо.


Буду разбираться...
PM MAIL   Вверх
rrrFer
Дата 11.6.2008, 07:44 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.5.2008
Где: Красноярск

Репутация: 0
Всего: 1



yorgan
отсторожно, у Павловской есть ошибка: на 274 странице она пишет, что в ostream определены функции seeg и tellg, на самом деле - seekp и tellp

Это сообщение отредактировал(а) rrrFer - 11.6.2008, 07:44
PM MAIL WWW ICQ   Вверх
yorgan
Дата 17.6.2008, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 5.6.2008

Репутация: нет
Всего: нет



Преподаватель задал еще такой вопрос: может ли быть виртуальный конструктор? Если нет, то почему?
И еще спросил можно ли в конструкторе (или деструкторе) использовать виртуальные функции?
Подскажите пожалуйста... ответы.
PM MAIL   Вверх
JackYF
Дата 17.6.2008, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 6
Всего: 162



Цитата(yorgan @  17.6.2008,  18:38 Найти цитируемый пост)
Подскажите пожалуйста... ответы. 

А прочитать самому?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
baldina
Дата 17.6.2008, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



yorgan, конструктор не может быть виртуальным по определению: полиморфизм включается, когда точно неизвестен тип объекта (точнее, выясняется в процессе выполнения). В конструкторе тип объекта известен всегда, уже на стадии компиляции.
Из конструктора виртуальные функции технически вызывать можно, однако объект не считается полностью сконструированным и готовым для использования пока не завершился конструктор, так что в общем случае поведение при таких вызовах не определено.
А вообще-то это не настолько простая тема, что бы объяснять её в двух словах, так что - книжку в руки.
PM MAIL   Вверх
yorgan
Дата 17.6.2008, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 5.6.2008

Репутация: нет
Всего: нет



Цитата(JackYF @  17.6.2008,  20:16 Найти цитируемый пост)
А прочитать самому?


Цитата(baldina @  17.6.2008,  21:34 Найти цитируемый пост)
так что - книжку в руки


К сожалению в книжках, которые есть у меня данные аспекты не рассматриваются и никак не комментируются (в Павловской и Березеных) :(
PM MAIL   Вверх
bsa
Дата 17.6.2008, 23:17 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



PM   Вверх
xvr
Дата 18.6.2008, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(yorgan @ 17.6.2008,  19:38)
Преподаватель задал еще такой вопрос: может ли быть виртуальный конструктор? 

Вообще то нет, но в Borland'овском расширении С++ для Builder/Delphi - могут (только преподавателю этого не говори, не оценит  smile )
Цитата

И еще спросил можно ли в конструкторе (или деструкторе) использовать виртуальные функции?
Можно, только они не будут там виртуальными. Зато сам деструктор может быть виртуальным, часто этого достаточно.

PM MAIL   Вверх
bsa
Дата 18.6.2008, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(xvr @ 18.6.2008,  11:23)
Цитата

И еще спросил можно ли в конструкторе (или деструкторе) использовать виртуальные функции?
Можно, только они не будут там виртуальными. Зато сам деструктор может быть виртуальным, часто этого достаточно.

Я бы уточнил, что нужно явно указывать принадлежность таких методов классу (Base::method() или Derived::method()).
PM   Вверх
yorgan
  Дата 18.6.2008, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 5.6.2008

Репутация: нет
Всего: нет



Правильно ли следующее высказывание или есть что добавить?

Цитата

Виртуальность предназначена для объекта, а на момент вызова конструктора объекта еще не существует. Конструктор предназначен для создания определенного типа объекта, если бы он был виртуальным, то мы бы не знали что создаем. 

На самом деле представим, что конструктор виртуален. Это уже замах на фабрики объектов. Так что можно предположить, что в этом есть плюс. Но теперь посмотрим с другой стороны. Допустим у нас базовый класс А, и два от него дочерних: Б и В. Конструктор А виртуален, соответвенно, по правилом "наследования виртуальности" классы Б и В тоже имею виртуальные конструкторы. Теперь мы вызываем
new A(), что должен сделать компилятор? Сделать объект Б или В? Необходима какая-то параметризация. Для этого и служат фабрики, которые знают и о классе Б и о классе В. Наш класс А ничего не знает о Б и о С.

Т.о., имхо, виртуальные конструкторы не могут быть из за:
1) Неоднозначность выбора потомка.
2) Отсутствие знаний о потомках.
и главное:
3) Мы не будем знать что создаем.

PM MAIL   Вверх
JackYF
Дата 18.6.2008, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 6
Всего: 162



yorgan, навскидку - правильное smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
rrrFer
Дата 18.6.2008, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 208
Регистрация: 11.5.2008
Где: Красноярск

Репутация: 0
Всего: 1



Цитата(yorgan @  18.6.2008,  15:54 Найти цитируемый пост)
Мы не будем знать что создаем.

есть такая вещь как интерфейсный класс, и там мы посути тоже не знаем что создаем...однако есть такое
PM MAIL WWW ICQ   Вверх
xvr
Дата 18.6.2008, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(bsa @ 18.6.2008,  11:36)
Цитата(xvr @ 18.6.2008,  11:23)
Цитата

И еще спросил можно ли в конструкторе (или деструкторе) использовать виртуальные функции?
Можно, только они не будут там виртуальными. Зато сам деструктор может быть виртуальным, часто этого достаточно.

Я бы уточнил, что нужно явно указывать принадлежность таких методов классу (Base::method() или Derived::method()).

При явном указании принадлежности (через :: ) виртуальности не будет не только в конструкторах и деструкторах  smile Если же из конструктора или деструктора вызвать виртуальную функцию не непосредственно (например так)
Код

class Test {
public:

 virtual ~Test() {func1();}

 void func1() {func2();}
 virtual void func2() {}
};

class Test2 : public Test {
public:
 ~Test2() {}

 virtual void func2() {}
};

Test* t=new Test2;
t->func1(); // Test::func1, Test2::func2
delete t; // Test2::~Test2, Test::~Test, Test::func1, Test::func2
то деструкторе Test2 будет вызванны функции Test::func1 и Test::func2. При вызове t->func1() будут вызванны Test::func1 и Test2::func2


Это сообщение отредактировал(а) xvr - 18.6.2008, 20:09
PM MAIL   Вверх
bsa
Дата 18.6.2008, 20:24 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(xvr @ 18.6.2008,  20:04)
то деструкторе Test2 будет вызванны функции Test::func1 и Test::func2. При вызове t->func1() будут вызванны Test::func1 и Test2::func2

отсюда вывод - нельзя вызывать виртуальные методы из конструктора и деструктора (если только через явное указание принадлежности классу).
PM   Вверх
xvr
Дата 19.6.2008, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(bsa @ 18.6.2008,  20:24)
Цитата(xvr @ 18.6.2008,  20:04)
то деструкторе Test2 будет вызванны функции Test::func1 и Test::func2. При вызове t->func1() будут вызванны Test::func1 и Test2::func2

отсюда вывод - нельзя вызывать виртуальные методы из конструктора и деструктора (если только через явное указание принадлежности классу).

Вывод неправильный - 
Draft 2005, 12.7 p4
Цитата

Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a
virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member)
or from a destructor, and the object to which the call applies is the object under construction or destruction, the function
called is the one defined in the constructor or destructor’s own class or in one of its bases, but not a function overriding
it in a class derived from the constructor or destructor’s class, or overriding it in one of the other base classes of the most
derived object (1.8). If the virtual function call uses an explicit class member access (5.2.5) and the object-expression
refers to the object under construction or destruction but its type is neither the constructor or destructor’s own class or
one of its bases, the result of the call is undefined. [ Example:
class V {
public :
virtual void f();
virtual void g();
};
class A : public virtual V {
public :
virtual void f();
};
class B : public virtual V {
public :
virtual void g();
B(V*, A*);
};
class D : public A , B {
public :
virtual void f();
virtual void g();
D () : B((A*) this , this ) { }
};
B::B(V* v , A* a) {
f (); / / calls V::f, not A::f
g (); / / calls B::g, not D::g
v->g (); / / v is base of B, the call is well-defined, calls B::g
a->f (); / / undefined behavior, a’s type not a base of B
}
—end example ]

PM MAIL   Вверх
bsa
Дата 19.6.2008, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



xvr, т.е. получается, что таблица виртуальных методов обновляется прямо перед входом в тело конструктора, но после инициализации всех членов класса. А в деструкторе с точностью до наоборот - после выхода из тела деструктора восстанавливается таблица класса предка. Правильно ли я понял?
PM   Вверх
mes
Дата 19.6.2008, 21:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(bsa @  19.6.2008,  21:04 Найти цитируемый пост)
xvr, т.е. получается, что таблица виртуальных методов обновляется прямо перед входом в тело конструктора, но после инициализации всех членов класса. А в деструкторе с точностью до наоборот - после выхода из тела деструктора восстанавливается таблица класса предка. Правильно ли я понял? 

что то я запутался, но нижеприведенный пример  выдает А:f1() A::f2() , что на мой взгляд не соотвествует написанному.. прошу пояснения 
Код

#include <cstdlib>
#include <iostream>

class A
{
    public:
        A() { f1(); }
        virtual ~A() { f2(); }

        virtual void f1() { std::cout << "A::f1()" << std::endl; };
        virtual void f2() { std::cout << "A::f2()" << std::endl; };
};
class A1: public A
{
    public:
        A1() {  }
       ~A1() {  }
        virtual void f1() { std::cout << "A1::f1()" << std::endl; };
        virtual void f2() { std::cout << "A1::f2()" << std::endl; };

};


int main()
{
    A1* pa = new A1();
    delete pa;

   system("pause");
    return 0;
}



Добавлено через 1 минуту и 43 секунды
а вобше разве это не UB ?


--------------------
PM MAIL WWW   Вверх
bsa
Дата 19.6.2008, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



mes, в том то и дело, что соответствует. Когда выполняется конструктор класса A, класс A1 еще не сконструировался и таблица виртуальных методов содержит указатели на методы класса А, который уже начал конструироваться, когда дело доходит до деструктора класса А, то класс А1 полностью деинициализировался и восстановил указатели на виртуальные методы класса А (ну или деструктор класса А это сделал перед входом в тело).
PM   Вверх
xvr
Дата 20.6.2008, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(bsa @ 19.6.2008,  21:04)
xvr, т.е. получается, что таблица виртуальных методов обновляется прямо перед входом в тело конструктора, но после инициализации всех членов класса. А в деструкторе с точностью до наоборот - после выхода из тела деструктора восстанавливается таблица класса предка. Правильно ли я понял?

Да. (Хотя технически таблицу виртуальных методов в деструкторе восстанавливает сам деструктор при входе, а не наследник при выходе, впрочем результат одинаковый)
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1436 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.