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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не пользуйтесь функциями типа get/set, объясните смысл написанного 
V
    Опции темы
Fazil6
Дата 12.7.2006, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Если это библиотечный класс, то имхо будет сложно учесть в нем все возможные способы работы с его данными.

с его данными тоже никто работать не собирается. smile 
Никто не должен предусматривать все способы. Пиши те способы, которые нужны на данный момент. Если потребуется новый способ, ты напишешь новый класс, наследник Write реализуя интерфейс нужным тебе способом и все. С работавшим до этого кодом ничего делать не нужно. 
PM MAIL   Вверх
likehood
Дата 12.7.2006, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Цитата(Fazil6 @  12.7.2006,  18:30 Найти цитируемый пост)
с его данными тоже никто работать не собирается

его данные использует метод write для вывода чего-то там на печать. 
PM MAIL   Вверх
Fazil6
Дата 12.7.2006, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

его данные использует метод write для вывода чего-то там на печать. 

ну да, конечно. Но это ведь данные этого класса(наследника Write) и нигде кроме самого класса они не используются. 

А... Я понял о чем вы. В том смысле, что данные Write используются в его наследнике? Так это все из тойже оперы. Классы не должны наследовать данные (бывают конечно исключения но это исключения). Ведь я стою на принципе, что данные не интересуют никого вне класса в том числе и наследников. Почему тогда они наследуются? Если они не интересуют никого Я уже писал выше, плохо когда детали реализации становятся частью интерфейса между родителем и наследником 
PM MAIL   Вверх
likehood
Дата 12.7.2006, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



что то я запутался: где у тебя храняться данные, которые надо вывести на печать или на экран?
в потомке Write или где-то еще? 
PM MAIL   Вверх
Fazil6
Дата 12.7.2006, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

что то я запутался: где у тебя храняться данные, которые надо вывести на печать или на экран?
в потомке Write или где-то еще? 

по моему очень простой пример. Функция write получает данные в аргументе от MyClass и куда-то их записывает.

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


666
**


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

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



Еще раз повторю свой вопрос: как метод write получит доступ к SomeData.
В данном случае это принципиально, поскольку класс Write и его наследники не имеют своих данных, а служат лишь для обработки данных, полученных извне. Если SomeData это простая структура, то тогда причем тут полиморфизм, обращаемся напрямую к полям этой структуры и выводим все на печать. Если структура SomeData изменится, придется переписывать много кода. Если же доступ к SomeData идет через get/set, то есть надежда, что придется переписать только эти методы.
Кстати, в данном первом примере вполне можно было обойтись без полиморфизма: просто наделать функции типа writeToFile, writeToPrinter и т.д. Как же тогда получить доступ к данным SetData без get/set и без нарушения инкапсуляции? 
PM MAIL   Вверх
Fazil6
Дата 12.7.2006, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



еще раз повтаряю
Цитата

Повторяю : это абстрактный пример. Не важно что такое SomeData. Считайте, что это int. Вы за деревьями леса не видите.


Добавлено @ 23:02 
Цитата

Если SomeData это простая структура, то тогда причем тут полиморфизм, обращаемся напрямую к полям этой структуры и выводим все на печать. Если структура SomeData изменится, придется переписывать много кода. Если же доступ к SomeData идет через get/set, то есть надежда, что придется переписать только эти методы.
Кстати, в данном первом примере вполне можно было обойтись без полиморфизма: просто наделать функции типа writeToFile, writeToPrinter и т.д. Как же тогда получить доступ к данным SetData без get/set и без нарушения инкапсуляции? 
 
ничего не понял. 

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


666
**


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

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



Цитата(Fazil6 @  12.7.2006,  23:50 Найти цитируемый пост)
Повторяю : это абстрактный пример.

Цель этого примера была конкретная: показать, что можно обойтись без меода get().
Я просто пытаюсь понять, действительно ли это так в данном "абстрактном" случае.

Цитата(Fazil6 @  12.7.2006,  23:50 Найти цитируемый пост)
ничего не понял.

Возможно, мы просто говорим о разных вещах. 
PM MAIL   Вверх
Fazil6
Дата 13.7.2006, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Цель этого примера была конкретная: показать, что можно обойтись без меода get().
Я просто пытаюсь понять, действительно ли это так в данном "абстрактном" случае.

там разве где-нибудь есть такой или подобный метод? 
PM MAIL   Вверх
likehood
Дата 13.7.2006, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Fazil6, похоже мы и вправду говорим о разных вещах. 
PM MAIL   Вверх
UnrealMan
Дата 13.7.2006, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
да. 
Это тоже самое, когда твои данные были бы просто protected

Нет, это не совсем то же самое.

Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
Если DerivedClass оперирует данными, то почему эти данные находятся в другом классе.

А если эти данные нужны в обоих классах (BaseClass и DerivedClass) и они используются несколькими общими методами? Предлагаешь продублировать все эти данные и связанные с их обработкой методы?

Код
class Base
{
    Data data;
protected:
    Data &GetData() { return data; }
public:
    ReturnType1 Method1() { /* использует data */ };
    ReturnType2 Method2() { /* использует data */ };
    ....
};

class Derived : public Base
{
    /* ну что, заново объявляем data, заново пишем Method1, Method2 и т.д.? */
    ReturnType3 Method3( /* может использовать data через GetData */ );
};


Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
Данные класса - это деталь реализации, когда в наследовании принимают участия данные, то детали реализации становятся частью интерфейса

Но интерфейс-то не открытый, а защищённый.

Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
а это плохо.

А терять в общности, которую мы могли бы выразить с помощью защищённых данных и применённых к ним методов, – это хорошо?

Цитата(UnrealMan @  12.7.2006,  10:26 Найти цитируемый пост)
Начнём с того, что непонятна природа SomeData. 

Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
никакого значения это не имеет

Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
Опять пишем класс на на все случаи жизни?

Эт я просто намекаю на то, что SomeData – это скорее некий универсальный тип, предназначенный для передачи данных в методы вывода, нежели тип поля класса (часто ли нужно выводить именно значение какого-то одного поля?). Т.е. метод output в MyClass должен преобразовывать члены-данные в данные вывода, которые дальше отправляются куда надо. Но тогда зачем вся эта возня с наследованием?

Код
#include <stdio.h>
#include <string>
#include <list>
#include <iostream>

namespace Output
{
    class Data
    {
        const std::string &str;
    public:
        Data(const std::string &s) : str(s) {}
        const std::string &GetStr() const { return str; }
    };

    typedef void (*Writer)(const Data &);
    
    void ToScreen(const Data &data)
    {
        printf("%s", data.GetStr().c_str());
    }
    void ToFile(const Data &data)
    {
        FILE *F = fopen("Output.txt", "ab");
        fprintf(F, "%s", data.GetStr().c_str());
        fclose(F);
    }
}

class UserClass
{
    std::list<std::string> ls;
    std::list<int> li;
    int nItems;
public:
    UserClass() { nItems = 0; }
    void AddItem(const std::string &s, int i)
    {
        ls.push_back(s);
        li.push_back(i);
        ++nItems;
    }

    void Write(Output::Writer writer)
    {
        char buf[0x40];
        std::string s;
        
        std::list<std::string>::const_iterator ls_i = ls.begin();
        std::list<int>::const_iterator li_i = li.begin();
        for (int i=0; i<nItems; ++i, ++ls_i, ++li_i)
        {
            s += *ls_i;
            sprintf(buf, " %d\n", *li_i); s += buf;
        }
        writer(Output::Data(s));
    }
};

int main()
{
    UserClass uc;
    uc.AddItem("One", 11);
    uc.AddItem("Two", 22);
    uc.AddItem("Three", 33);

    int OutputKind;
    Output::Writer f;
    std::cin>>OutputKind; std::cout<<'\n';
    if (OutputKind)
        f = &Output::ToScreen;
    else
        f = &Output::ToFile;
    uc.Write(f);

    return 0;
}


Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
Необходимость в доступе к данным == неправильный дизайн. Проектирование + виртуальные функции - вот инструмент решения проблем. Сколько еще раз повторить?

Укажи мне на какое-нибудь преимущество твоего способа перед тем, который только что продемонстрировал я.

Цитата(Fazil6 @  12.7.2006,  12:50 Найти цитируемый пост)
а тут уж что тебя не устраивает?

Забота о времени жизни каких-то левых вспомогательных объектов. 

Это сообщение отредактировал(а) UnrealMan - 13.7.2006, 12:02
PM MAIL   Вверх
Fazil6
Дата 13.7.2006, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



UnrealMan, 
Цитата

А если эти данные нужны в обоих классах (BaseClass и DerivedClass) и они используются несколькими общими методами? Предлагаешь продублировать все эти данные и связанные с их обработкой методы?
Код
class Base
{
    Data data;
protected:
    Data &GetData() { return data; }
public:
    ReturnType1 Method1() { /* использует data */ };
    ReturnType2 Method2() { /* использует data */ };
    ....
};

class Derived : public Base
{
    /* ну что, заново объявляем data, заново пишем Method1, Method2 и т.д.? */
    ReturnType3 Method3( /* может использовать data через GetData */ );
};


из этого примера вообще непонятно, зачем нужен наследник. Я вам говорю, что методы get и set, наследование данных как правило свидетельствуют о плохом дизайне. Почти всегда можно сделать по настоящему ОО классы и на самом деле текста будет меньше и модель будет гибче и в сопровождении будет проще. А вы мне что отвечаете? "Нет! Доступ к данным необходим! Без него вот этот пример (здесь идет пример) не работает!" так я повторю - неправильный дизайн. Вот этот твой пример ничего не доказывает. Я вообще из него не вижу никаких резонов иметь родителя и наледника. Включи Method3 в родителя и все. 

Цитата

Эт я просто намекаю на то, что SomeData – это скорее некий универсальный тип, предназначенный для передачи данных в методы вывода, нежели тип поля класса (часто ли нужно выводить именно значение какого-то одного поля?). Т.е. метод output в MyClass должен преобразовывать члены-данные в данные вывода, которые дальше отправляются куда надо. Но тогда зачем вся эта возня с наследованием?

что значит зачем? код один и тот-же, но используется в зависимости от действительного типа аргумента. У меня для вывода может  использоваться одна единственная (невиртуальная, неперегруженная, никак не переопределенная функция), а результат я буду получать в ней совершенно разный в зависимости от типа аргумента переданного в нее. Вот зачем наследование и полиморфизм.

Теперь по поводу твоего последнего примера.
Ржунимагу.
Цитата

Укажи мне на какое-нибудь преимущество твоего способа перед тем, который только что продемонстрировал я.

никакого. Ты написал абсолютно тоже самое, что писал я. Я могу конечно начать придираться к реализации (а есть к чему у тебя придираться и даже очень, особенно после Забота о времени жизни каких-то левых вспомогательных объектов. ), но сейчас мы говорим о другом.
есть класс UserClass, у него есть данные. Но ведь у него нет методов get/set и ничего похожего на них. Вывод данных осуществляет сам класс UserClass, он решает что выводить. Где в твоем примере кому-то потребовались данные от UserClass? Все нормально. writer - это таже самая виртуальная функция по сути. Просто виртуальность ее ты сам обеспечиваешь. Ну пожалуста.

А вот это 
Цитата

class Data
    {
        const std::string &str;
    public:
        Data(const std::string &s) : str(s) {}
        const std::string &GetStr() const { return str; }
    };

я вообще не замечаю. Если вокруг переменной нарисовать фигурные скобки и написать слово class, то классом эта конструкция не станет. Это в данном примере не класс, а структура данных, и как я писал выше тут смысл в самих данных и доступ к ним какбы очевидно должен быть, иначе что это за данные, которые я не могу видеть. Это тоже самое, что и SomeData в моем примере и если вас так сильно сбило всех с толку это слово то я уже писал, считайте это int или string или как хотите

 
PM MAIL   Вверх
UnrealMan
Дата 13.7.2006, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
из этого примера вообще непонятно, зачем нужен наследник. 

Ладно, приведу пример поконкретней.

Пусть у нас имеется игра. В ней есть два вида персонажей: игрок (управляется пользователем) и монстр (управляется программно – простеньким искусственным интеллектом). Каждый персонаж обладает следующим набором свойств: положение в пространстве Pos, запас здоровья Health, запас брони Armor. Каждому персонажу можно нанести повреждение (Damage), проверить, не мёртвый ли он (IsDead), а также переместить в пространстве (Move) (каким образом – зависит от вида персонажа).

Помимо этого, игрок обладает неким ограниченным количеством боеприпасов WeaponAmmo, а также может подымать аптечки (PickUpHealthPack) и броню (PickUpArmor) с поля боя, монстр же может атаковать неограниченно долго и не может подымать аптечки и броню. Интеллект монстра руководствуется неким своим текущим режимом поведения Mode (это может быть, скажем, яростная атака или стрельба в отступлении в игрока), а также запасом своих здоровья и брони (атаковать, когда много, отступать, когда мало). Вот примерный код:

Код
struct Vect3d { double x,y,z; /* далее операции с вектором */ };

class Pawn
{
    Vect3d Pos;
    int Health, Armor;
protected:
    Vect3d &GetPos() { return Pos; }
    int &GetHealth() { return Health; }
    int &GetArmor()  { return Armor; }
public:
    void Damage(int damage)
    {
        int ArmorDam = min(Armor, (damage+1)/2);
        Armor  -= ArmorDam;
        Health -= damage-ArmorDam;
    }
    bool IsDead() { return Health<=0; }
    virtual void Move() = 0; // что бы это ни было, здесь используется Pos
    // ... // ещё какие-то члены
};

class Player : public Pawn
{
    int WeaponAmmo;
public:
    PickUpHealthPack() { GetHealth() = min(100, GetHealth()+20); }
    PickUpArmor()      { GetArmor() = 100; }
    void Move()
    {
        /* перемещаем игрока, используя состояние клавиш клавиатуры */
    }
    // ... // ещё какие-то члены
};

class Monster : public Pawn
{
    int Mode;
public:
    void Move()
    {
        /* перемещаем монстра, используя простой ИИ,
        учитывающий текущие значения Mode, Health и Armor  */
    }
    // ... // ещё какие-то члены
};

Где тут «неправильный» дизайн? И как его сделать «правильным»? Ваш ход, сэр.

Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
Включи Method3 в родителя и все.

Ну-ну, напихать в родителя всё, что только можно... Тогда действительно непонятно, зачем нужно наследование.

Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
У меня для вывода может использоваться одна-единственная (невиртуальная, неперегруженная, никак не переопределенная функция), а результат я буду получать в ней совершенно разный в зависимости от типа аргумента переданного в нее. Вот зачем наследование и полиморфизм.

Теперь по поводу твоего последнего примера.

Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
никакого. Ты написал абсолютно тоже самое, что писал я.

Не понял. Если твои наследование и полиморфизм здесь ничего не дают (кроме лишнего геморроя с ворохом классов, для которых ещё нужно создавать объекты – по сути вспомогательные), то зачем вообще их тут было использовать?

Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
Я могу конечно начать придираться к реализации (а есть к чему у тебя придираться и даже очень, особенно после Забота о времени жизни каких-то левых вспомогательных объектов. ), но сейчас мы говорим о другом.

Цитата(Fazil6 @  13.7.2006,  12:51 Найти цитируемый пост)
writer - это таже самая виртуальная функция по сути.

Давай-ка не будем наводить тень на плетень. Если бы всегда от наследования и (или) виртуальных функций можно было б освободиться так же легко, как это сделал я, смысл в их использовании был бы под сомнением. Я всего лишь клоню к тому, что наследование в твоём примере не нужно и только загромождает код, а следовательно, такой пример использования полиморфизма неудачен. 

Это сообщение отредактировал(а) UnrealMan - 14.7.2006, 09:26
PM MAIL   Вверх
Fazil6
Дата 15.7.2006, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Где тут «неправильный» дизайн? И как его сделать «правильным»?
ты считаешь свои решения безупречными и переубеждать тебя я не собираюсь. В твоем примере реализация монстров и солдат связаны между собой. Мы не можем внести никаких измений в использование этих закрытых переменных для одного класса без учета того как это может отразиться на другом. Многие знают пример с эмулятором полетов австралийских ВВС когда стадо кенгуру начинало перегрупировываться и обстреливать самолеты "стингерами".
 Ладно. Примем твою идею с общностью и необходимостью доступа к этим данным из наследников. Используем защищенный интерфейс. Хорошо. Избранный вариант самый гибкий, самый красивый, самый короткий и самый опасный. Это немногим лучше чем открытые данные. Этот интерфейс будет использоваться именно как доступ к переменным (ты так и пользуешься). Весь код использующий этот интерфейс становится зависимым от его реализации. Опять же, имя метода для установки значения Get - это плохой дизайн.
Если уж делать, то
Код

Vect3d GetPos() const { // бла-бла }
void SetPos(Vect3d) { // бла-бла }
по крайней мере это уменьшит зависимость наследника от родителя. Замечания по поводу эфективности передачи по ссылке здесь не принимаются.
Цитата

Ну-ну, напихать в родителя всё, что только можно... Тогда действительно непонятно, зачем нужно наследование.

совсем не для того, чтобы размазывать реализацию по нескольким классам.

Цитата

Не понял. Если твои наследование и полиморфизм здесь ничего не дают (кроме лишнего геморроя с ворохом классов, для которых ещё нужно создавать объекты – по сути вспомогательные), то зачем вообще их тут было использовать?

Цитата

Давай-ка не будем наводить тень на плетень. Если бы всегда от наследования и (или) виртуальных функций можно было б освободиться так же легко, как это сделал я, смысл в их использовании был бы под сомнением. Я всего лишь клоню к тому, что наследование в твоём примере не нужно и только загромождает код, а следовательно, такой пример использования полиморфизма неудачен. 

не думаю, что первоочередная задача программиста неиспользование виртуальных функций. Я не считаю, что твой способ без классов чем-то лучше, и посмотри на название ветки - это был не пример использования полиморфизма, а пример неиспользования доступа к данным. 
 
PM MAIL   Вверх
Meeer
  Дата 15.7.2006, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот почитал-почитал всю эту дискуссию.
Нам Rockie дает вырезку из какой-то книги. Как мы видим Fazil6 также читал (или читает) эту самую книгу, и

Цитата

вообще-то я советую всем, кто не читал эту книжку, прочитать, хоть она и не первой свежести. Автор четко знает о чем пишет, все с прекрасными примерами из жизни и юмором. Читается очень увлекательно   


Fazil6
Я тебя понял. Но это в теории так идеально. А на практике довольно таки неудобно (судя из твоего примера там больше путаницы). Тем более всеравно те же самые значения передаются как параметр smile.

"ООП С++", автор Айра Пол, второе издание:
Цитата

...
В С++ новое понятие классов предоставляет механизм инкапсуляции (encapsulation) для реализации АТД (абстрактный тип данных). Инкапсуляция сочетает в себе, с одной стороны, внутренние детали реализации конкретного типа и, с другой, доступные извне операции и функции, которые могут действовать на объекты этого типа. Детали реализации могут быть недоступны для программы, которая использует данный тип. Например, стек может быть реализован как массив фиксированной длинны, а доступные всем операции должны включать в себя функции push(поместить в стек) и pop (извлеч из стека). Изменение внутренней реализации на связной список не должно повлиять на то, как push и pop используются снаружи класса ... Реализация стека скрыта от его клиентов.
...


smile 
PM MAIL   Вверх
Страницы: (7) Все « Первая ... 3 4 [5] 6 7 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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