Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/56: Рейтинг темы: голосов - 56, средняя оценка - 4.59
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
1

Перегрузка конструктора копирования и оператора присвоения

11.02.2012, 14:08. Показов 11753. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет, сразу к делу. После прочтения 11 главы Лафоре столкнулся с такой бедой как понятие перегрузка оператора присвоения. Дело в том что Лафоре говорит что именно оператор присвоения является уникальным и не наследуется. Но когда создаёшь указатель на базовый класс там естественно делаешь все методы виртуальными (для полиморфизма), при раз адресации указателя происходит вызов перегруженного оператора присвоения базового класса а не производного который по факту там находиться!! Как же так? Естественно что я перегрузил эти конструкторы и в производных классах. Код ниже подскажите как мне быть?? Как вызвать нужный мне перегруженный оператор?
Базовый класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//класс издательство
class publication
{
    protected: 
        static const int sciMAX=100;//максимальный размер символьного массива
        metring* ch_name;//название
        float f_price;//цена
    public:
        //конструктор без параметров
        publication(void);
        //конструктор с двумя параметрами
        publication(char* ch_name, float f_price);
        //конструктор копирования
        publication(publication&);
        //диструктор
        virtual~publication(void);
        //ввод данных
        virtual void put_into_the_class(void)=0;//чисто виртуальная фукция
        //вывод данных на экран консоли
        virtual void get_out_of_the_class(void);
        //оператор присвоения
        virtual publication& operator = (publication&);
};
Конструктор копирования базового класса
C++
1
2
3
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса
Перегрузка оператора присваения
C++
1
2
3
4
5
6
7
8
9
10
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
Производный класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//класс книга
class book : public publication
{
    private:
        int i_how_meny_pic;//количество страниц
    public:
        //конструктор без параметров
        book(void);
        //конструктор копирования
        book(book&);
        //конструктор с тремя параметрами
        book(int,char*,float);
        //ввод данных
        void put_into_the_class(void);
        //вывод данных на экран консоли
        void get_out_of_the_class(void);
        //операция присвоения
        book& operator = (book&);
};
Конструктор копирования для производного (от класса издательство) класса книга
C++
1
2
3
4
5
6
7
8
//конструктор копирования
book::book(book& val)
{
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса   
    i_how_meny_pic = val.i_how_meny_pic;//копирую количество страниц в книге
}
Перегрузка операции присвоения для производного (от класа издательство) класса книга
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//операция присвоения
book& book:: operator = (book& val)
{
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    i_how_meny_pic = val.i_how_meny_pic;//копирую количество страниц в книге
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
}
Производный класс "тип" от класса издательство
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//класс тип
class type : public publication
{
    private:
        float f_time;//время записи книги в менутах
    public:
        //конструктор без параметров
        type(void);
        //конструктор копирования
        type(type&);
        //конструктор с тремя параметрами
        type(float,char*,float);
        //ввод данных
        void put_into_the_class(void);
        //вывод данных на экран консоли
        void get_out_of_the_class(void);
        //оператор присваения
        type& operator = (type&);
 
};
Конструктор копирования производного(от класса издательство) класса "тип"
C++
1
2
3
4
5
6
7
8
//конструктор копирования
type::type(type& val)
{
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса   
    f_time = val.f_time;//коприрую время записи книги в минутах
}
Перегрузка оператора присваения производного (от класса издательство) класса "тип"
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//оператор присваения
type& type:: operator = (type& val)
{
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    f_time = val.f_time;//коприрую время записи книги в минутах
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
}
Использование инструметрария:
Идей заключается в следующем создается в динамической памяти массив указателей на базовый класс.
И процессе работы программы на уровне пользователя решается какой класс будет создан вот кусок кода
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
            std::cout<<"Выбирите тип книги audy или paper (a,p) :";
            std::cin>>str_val;
            if(str_val=="paper"||str_val == "p")
            {
                *(publist+n)=new book;//выделение памяти под необходимый производный класс
                (*(publist+n))->put_into_the_class();//взятие данный от пользователя
                n++;//увеличение счётчика элиментов массива
                break;//выход из внутреннего цикла
            }
            else if(str_val =="audy"||str_val == "a")//если ползователь ввел аудио книгу
            {
                *(publist+n)=new type;//выделение памяти под необходимый производный класс
                (*(publist+n))->put_into_the_class();//взятие данный от пользователя
                n++;//увеличение счётчика элиментов массива
                break;//выход из внутреннего цикла
            }
Далее предусмотрено динамическое выделение памяти при необходимости т.е. если пользователь не угомонился и продолжает вводить данные в массив вот код:
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
if(n>=ilenpublist)//елси не хватает места для элементов в массиве то перевыделяем память
         {
            publication** temp = new publication*[ilenpublist];//временный массив для переброски данных
            for(int i =0 ; i<ilenpublist;i++)
            {   //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                if(dynamic_cast<book*>(*(publist+i)))
                {
                    *(temp+i) = new book;//выделяю память
                    *(*(temp+i))=*(*(publist+i));//побитовое копирование между объектами
                }
                //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                else if(dynamic_cast<type*>(*(publist+i)))
                {
                    
                    *(temp+i) = new type;//выделяю память
                    *(*(temp+i))=*(*(publist+i));//побитовое копирование между объектами
                }
            }
            //освобождаю память для перевыдиления
            for(int i =0 ; i<ilenpublist;i++)
            {delete publist[i];}
            //выделяю новый массив на один элемент больше чем предыдуший
            publist = new publication*[n+1];//указатель на базовый класс
            //возвращаю на место уже введеный данные пользователем
            for(int i=0;i<ilenpublist;i++)
            {   //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                if(dynamic_cast<book*>(*(temp+i)))
                {
                    *(publist+i) = new book;//выделяю память
                    *(*(publist+i))=*(*(temp+i));//копирование между объектами
                }
                //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                else if(dynamic_cast<type*>(*(temp+i)))
                {
                    
                    *(publist+i) = new type;//выделяю память
                    *(*(publist+i))=*(*(temp+i));//копирование между объектами
                }
                
            }
            ilenpublist = n;//контроль реального количества элементов в массиве
            //освобождаю память из под временной переменной
            for(int i =0 ; i<ilenpublist-n;i++)
            {delete temp[i];}
         }
Вот в этой строке 31 и 38 почему то вызывается оператор присвоения базового класса а не соответствующего производного
C++
1
*(*(publist+i))=*(*(temp+i));//копирование между объектами
Как мне разрешить эту ситуацию?

Добавлено через 1 час 11 минут
Если кому интересно, то я решил эту проблему вот так:
для класса "тип"
C++
1
2
3
//преобразую указатель на базовый класс на указатель на соответствующий производныый
//поэлиментное копирование между объектами
*(dynamic_cast<type*>(*(publist+i)))=*(dynamic_cast<type*>(*(temp+i)));
для класса книга
C++
1
2
3
//преобразую указатель на базовый класс на указатель на соответствующий производныый
//поэлиментное копирование между объектами
*(dynamic_cast<book*>(*(publist+i)))=*(dynamic_cast<book*>(*(temp+i)));
Теперь всё работает как надо т.е. вызывается перегруженный оператор присваения именно того класса на который указывает указатель в данный момент.
НО возник вопрос-почему так? Неужели если работаешь с указателями при полиморфизме необходимо постоянно вручную преобразовывать указатели? И почему казалось бы альтернативный способ не приносит тех же результатов
C++
1
2
*(publist+i) = dynamic_cast<book*>(*(publist+i))
*(*(publist+i)) = *(*(temp+i));
Это всё очень странно и не понятно, да и самое удивительно то что перед операцией присвоения я проверял с помощью функции typeid какому классу принадлежит созданный объект. Так вот всё нормально
функция показывала что в памяти содержиться тот или иной но нужный в конкретной ситуации объект, но всеравно продолжал вызываться перегруженный метод присвоения базового класса.
Может кто нибудь объяснить? Ни у Лафоре ни у Павловской я этого не нашёл
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.02.2012, 14:08
Ответы с готовыми решениями:

Перегрузка оператора присвоения
// radius.cpp: определяет точку входа для консольного приложения. // #include &quot;stdafx.h&quot;...

Перегрузка оператора присвоения в enum class
Всем доброго дня. Есть enum: typedef unsigned char byte; enum class MyEnum : byte { A,...

Явное определение конструктора копирования и оператора присваивания
Объясните, пожалуйста, нужно ли явно определять конструктор копирования (**) и оператор...

Конструктор копирования и перегрузка оператора присваивания
Здравствуйте! Возникла следующая проблема: не могу перегрузить оператор присваивания и сделать...

18
2848 / 1997 / 986
Регистрация: 21.12.2010
Сообщений: 3,705
Записей в блоге: 10
11.02.2012, 15:25 2
сигнатуры должны совпадать с базовым классом
virtual publication& operator = (const publication&);
type& type::operator = (const publication&);
book& book::operator = (const publication&)
0
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 15:58  [ТС] 3
Сейчас попробую...

Добавлено через 6 минут
Нет такой Вариант не годиться т.к. publication я вляется базовым и не знает и уж темболее не имеет соответсвующих полей производных классов. Если сделать как говорите вы то будет потеря данных.
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 16:06 4
Цитата Сообщение от stawerfar Посмотреть сообщение
Лафоре говорит что именно оператор присвоения является уникальным и не наследуется
раз вас Лафоре не убелил, то хотя бы подобные конструкции должны вас убедить
Цитата Сообщение от stawerfar Посмотреть сообщение
*(dynamic_cast<type*>(*(publist+i)))=*(dynamic_cast<type*>(*(temp+i)));
еще раз: оператор присвоения является уникальным и не наследуется. и в записи
Цитата Сообщение от stawerfar Посмотреть сообщение
virtual publication& operator = (publication&);
писать virtual бесполезно. не будет он виртуальным.
1
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 16:17  [ТС] 5
Спасибо за коментарий, но мне показалось что Вы не поняли сути произходящего.
Да Лафоре сказал что не наследуется, а в моём случае наоборот все время вызывался метот базового класса(то есть можно сказать что "наследовался", по факту это конечно не так это я для объяеснения), когда я вытаскивал содержимое из указателей то там каждый раз были разные производные объекты. Следовательно по словам Лафоре метод "=" базового класса не должен был вызываться. Надеюсь Вы прости те меня за столь подробное объяснение, но надеюсь это прольёт свет на ситуацию.
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 16:28 6
вызывается оператор = для статического типа указателя, а не динамического
C++
1
2
3
4
5
6
7
8
publication* p1, p2;
book b1, b2;
 
p1 = &b1;
p2 = &b2;
// вызывается publication::operator= , а не book::operator= ,
// т.к. статический тип объекта, на который указывают указатели, publication
*p1 = *p2;
Добавлено через 1 минуту
вот вам вдогонку. не запуская программы, подумайте, что она выведет... а потом проверьте
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
class A
{
    int x;
};
 
class B: public A
{
    int x;
};
 
int
main()
{
    B b;
    A* pb = &b;
    std::cout << sizeof b << "=" << sizeof *pb << std::endl;
    return 0;
}
1
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 16:43  [ТС] 7
Вы меня совсем что ли за идиота держите? Либо просто выпендриваетесь передо мной?
Люди обычно спорят когда не понимают либо говорят о разных вещах, так Вот в место того что бы пробовать объяснять то что я и так знаю. Я Вам посоветаю внимательно прочитать мой вопрос, а не придумывать его.

Добавлено через 5 минут
Мой Вам втречны вопрос: объект какого класса находиться в *(*(temp+i))
C++
1
2
*(temp+i) = new book;//выделяю память
*(*(temp+i))=*(*(publist+i));//побитовое копирование между объектами
А уж потом объясняйте мне ...
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 16:56 8
Цитата Сообщение от stawerfar Посмотреть сообщение
Я Вам посоветаю внимательно прочитать мой вопрос
а я Вам посоветую излагать его по-русски.
хотели знать почему
Цитата Сообщение от stawerfar Посмотреть сообщение
почему то вызывается оператор присвоения базового класса а не соответствующего производного
C++
1
*(*(publist+i))=*(*(temp+i));//копирование между объектами
так я вам и обьяснил, что
Цитата Сообщение от retmas Посмотреть сообщение
вызывается publication::operator= , а не book::operator= , т.к. статический тип объекта, на который указывают указатели, publication

Не по теме:

Цитата Сообщение от stawerfar Посмотреть сообщение
Вы меня совсем что ли за идиота держите?
до этого вопроса - нет.

2
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 17:06  [ТС] 9
Я так и думал!! Я полностью с Вами согласен. И это моё упущение что я не предусмотрел что ни кто ни будет в вчитываться в код. И надо было по лучше формировать вопрос. Дело в том что я заметил на этапе отладки что даже вот тут
C++
1
2
*(temp+i) = new book;//выделяю память
*(*(temp+i))=*(*(publist+i));//побитовое копирование между объектами
не смотря на то что там находиться объект класса "книга" причем и слева и справа(второе не важно), почему-то вызывается "не наследуемая" операция присвоения базового класса.
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 17:21 10
ну так в чем проблема? так и должно быть: оператор= не наследуется, поэтому для указателей на publication вызывается publication::operator= . и нет тут никакого "наследования". вы просто запутались, что значит "наследует".
а вот если бы вызывался book::operator= для указателей на publication(при их разыменовании), то это и было бы наследованием

Добавлено через 7 минут
если вам понятно это
Цитата Сообщение от retmas Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
publication* p1, p2;
book b1, b2;
 
p1 = &b1;
p2 = &b2;
// вызывается publication::operator= , а не book::operator= ,
// т.к. статический тип объекта, на который указывают указатели, publication
*p1 = *p2;
то почему не пнятно, что здесь ситуация аналогичная
Цитата Сообщение от stawerfar Посмотреть сообщение
C++
1
2
*(temp+i) = new book;//выделяю память
*(*(temp+i))=*(*(publist+i));//побитовое копирование между объектами
1
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 17:27  [ТС] 11
Запутался? Ну тогда объясните что по чему это помогает в этой ситуации
Т.е. если сделать так то все работает т.е.
C++
1
*(dynamic_cast<type*>(*(temp+i)))=*(dynamic_cast<type*>(*(ipublist+i)));
а так нет
C++
1
*(*(temp+i))=*(*(ipublist+i));
Вопрос что находиться в *(*(temp+i))?
следующая функция показывает что это объект класса type "тип"
C++
1
std::cout<<typeid(*(*(temp+i))).name()<<std::endl;//type
У этого объекта есть перегруженные операции присвоения и копирования.
Вопрос тогда почему объект типа "тип" вызвает метод базового класса "издательство".
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 17:40 12
не нужно путать статические и динамические типы. первые определяются на этапе компиляции, вторые - на этапе выполнения.
на этапе выполнения в *(*(temp+i)) находится объект типа book(или что там у вас). но компилятору нас*ать, что там на этапе исполнения. на этапе компиляции все что он видит - указатель на publication и генерирует соответствующий код для объектов типа publication. для того, чтобы он на этапе компиляции генерил присваивание book::operator=, придется явно ему это указать, например, так
C++
1
*((book*)*(temp+i))=*((book*)*(ipublist+i));
но это совсем не ок и опасно. для этого и придумали dynamic_cast, который безопасен в плане полиморфного приведения типов на этапе выполнения(!!!), т.е. на этапе выполнения у вас и будет по функциональности это
C++
1
*((book*)*(temp+i))=*((book*)*(ipublist+i));
1
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 17:48  [ТС] 13
retmas .. так бы сразу и сказали. Большое спасибо что пролили свет на этот процесс, ну я не удовольствуюсь только Вашим ответом. Позволю себе спросить у Вас где Вы это читали? Я бы хотел поподробней эту ситуацию изучить. Я конечно понимаю что Вы можете мне сказать спросит у Googlе, но всё же может посоветуете где мне поподробней почитать по позднее связывание.
Да и ещё вопрос, на сколько я успел заметить такие проблемы возникают только с оператором присвоения?!
Да и ещё Вы показали довольно странный синтаксис
C++
1
2
1
 *((book*)*(temp+i))=*((book*)*(ipublist+i));
я такого раньше на всречал! Объясните пожалуйста
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 17:56 14
Цитата Сообщение от stawerfar Посмотреть сообщение
Вас где Вы это читали?
У Страуструпа детально изложены все моменты языка. Страницы не скажу, т.к. под рукой нет. Но скажу одно - не нашли объяснения какого-то ключевого момента языка - читайте еще раз и внимательнее.

Цитата Сообщение от stawerfar Посмотреть сообщение
довольно странный синтаксис
приведение в стиле С
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
11.02.2012, 17:58 15
stawerfar, чтобы сразу получить ответ, вы должны были выложить сюда минимальный код, повторяющий ошибку вашего изначального кода. Я, лично, зайдя в эту тему и увидев количество кода, просто сразу ушёл отсюда, потому что разбираться во всём этом - сломать глаза и мозг. Я думаю, так поступили многие. Только retmas был в настроении ответить, за что ему плюс.
2
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 18:07  [ТС] 16
Цитата Сообщение от retmas Посмотреть сообщение
не нашли объяснения какого-то ключевого момента языка - читайте еще раз и внимательнее.
Это первое что я сделал. Я же писал об этом в начале. Про Бьёрна Страуструпа я слышал но книги не имею, пока..
Ещё раз спасибо,бы ло приятно с Вами беседовать!

Добавлено через 4 минуты
Цитата Сообщение от silent_1991 Посмотреть сообщение
stawerfar, чтобы сразу получить ответ, вы должны были выложить сюда минимальный код, повторяющий ошибку вашего изначального кода. Я, лично, зайдя в эту тему и увидев количество кода, просто сразу ушёл отсюда, потому что разбираться во всём этом - сломать глаза и мозг. Я думаю, так поступили многие. Только retmas был в настроении ответить, за что ему плюс.
На верно Вы правы, просто исходя из предыдущего опыта "выкладывания" всего кода - начинаются по моему не нужные разговоры которые просто уводят от темы. Ну например "божемой какой ужастный код",
"отвратительно" и т.д.. В ответ этому пишешь ребята "Вы себя нормально чувствуете?". А модератор посетивший чат не вникая в суть БАЦ - 30 ... балов.

Добавлено через 3 минуты
Да и к стати я выложил минимальный мой код.
Вот его не оптимизированная копия (оригинал):
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
#include<iostream>
#include<string>
#include<typeinfo>
#include<conio.h>
/*В этом листенге сделано два упражнения по книге Лафоре
Идей заключается в следующем создается в динамической памяти массив указателей на базовый класс.
И процессе работы программы на уровне пользователя решается какой класс будет создан. После используя
полиморфизм вывожу данные из разных классов, на экран однотипным методом
/************************************************************************************************/
enum direction{LOWEST,DESCENDING};//перечисление направления сортировки
/**************************************************************************************************************************************/
 
class metring
{
protected:
    char* ch_pt;//для хранения выражения введённого пользователем
    int imax_fmas;//максимально количество элементов массива fmas
    int icount;//счетчик указателей на строку
    float* fmas ;//массив вещественных чисел
    //объяевление дружественных класов
    friend class publication;
    friend class book;
    friend class type;
public:
    //конструктор без параметров
    metring(void);
    //конструктор содним параметром
    metring(char* ch_c);
    //деструктор для освобождение памяти
    virtual~metring(void);
    //операция преобразования из объекта класса в float*
    operator float*(void);
    //возврат количества элементов в вещественном массиве
    int return_imax_fmas(void);
    //получение от пользователя набора чисел 
    void get_number(void);
    //оператор для преобразования из объекта в массив символов
    operator char*(void);
};
 
//конструктор без параметров
metring::metring(void):imax_fmas(1),icount(1)
{
    setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
    ch_pt = new char[2];//первый раз выдиляю память под строку
    ch_pt[0]='\0';//принудительное указаник конца строки
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел
}
//конструктор содним параметром
metring::metring(char* ch_c):icount(1)
{
    
    setlocale(LC_ALL,"Russian");//разрешаю вывод Русского языка
    ch_pt = new char[2];//первый раз выдиляю память под строку
    ch_pt[0]='\0';//принудительное указаник конца строки
    imax_fmas=1;
    fmas = new float[imax_fmas];//создаём подходящий по размерам массив для чисел  
 
    
    if(strlen(ch_c)>1)
    {delete []ch_pt;}//освобождаю ранее выделенную память т.к. она не достаточна для хранения новой строки 
    ch_pt = new char [strlen(ch_c)+1];
    ch_pt[0]='\0';//принудительное указаник конца строки
    strcpy(ch_pt,ch_c);
    ch_pt[strlen(ch_c)]='\0';//принудительное указаник конца строки
}
//деструктор для освобождение памяти
metring::~metring(void)//освобождаю память
{delete []ch_pt;delete []fmas;}
//получение от пользователя набора чисел 
void metring::get_number(void)
{
    int ilen = 1;//для хранения длинны строки
    char* ch_pt_temp ;//временный банк для обмена
    char ch_temp[2]="e";//инициализация любым значение отличным от нуля и не равным 13(знаку Enter)
    //создание строки необходимого размера для хранения строки ch_c
    while(ch_temp[0]!=13)//продолжать пока пользователь не нажмёт клавишу Enter
    {
        ch_pt_temp = new char[strlen(ch_pt)+2];//выделяю память под переменную для обмена
        ch_pt_temp[0]='\0';//принудительное указаник конца строки          
        bool flag=true;//флаг для инкримента счетчика символов
        ch_temp[0] = getche();//отобразить символ и записать его значение в переменную типа char
        if(ilen!=1&&ch_temp[0]!=13)//если ilen!=1 и ch_temp!=Enter 
        {                                   //  то освобождаем память для перевыдиления
            //перед освобождением памяти делаю копию значения строки
            //копируем сиволы в нашу строку с нулевым символом
        
            for(int i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt)+1;i++,r++)
            {
                ch_pt_temp[r]=ch_pt[i]; 
            }
            ch_pt_temp[strlen(ch_pt_temp)+1];//принудительное завершение строки
            delete []ch_pt;//освобождаю выделенную память
            if(ch_temp[0]==8&&strlen(ch_pt_temp))
            {
                std::cout<<"\x20\x08";//затираем предыдущий символ знаком пробела и перемещаем курсор
                ilen--;//уменьшаем значение количество символов в строке
                flag=false;
            }
            else if(ch_temp[0]==8&&strlen(ch_pt_temp)<=0)
            {
                std::cout<<"\x3A";
            }
            ch_pt=new char[ilen+2];//заного выделяю память 1 для нового сивола другой для знака \0 конца строки
            ch_pt[0]='\0';//принудительное указаник конца строки
            //возвращаю значение строки предшествующие перевыдилинию памяти
            //копируем сиволы в нашу строку с нулевым символом
            int itemplen=(strlen(ch_pt_temp)==ilen-2)?ilen-1:ilen;
            for(int i = 0, r = strlen(ch_pt); i < itemplen+1;i++,r++)
            {
                ch_pt[r]=ch_pt_temp[i]; 
            }
            if(strlen(ch_pt_temp)!=ilen-2)
            {ch_pt[ilen-1]='\0';}
            
        }
        if(ch_temp[0]!=13&&ch_temp[0]!=8)//если ch_temp!=Enter помещаем символ в строку
        {
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt); i < strlen(ch_temp)+1;i++,r++)
            {
                ch_pt[r]=ch_temp[i];    
            }
            
        }
        delete[]ch_pt_temp;//освобождаем память
        if(flag)
        {ilen++;}//инкременация счетчика символов
    }
    imax_fmas=ilen;//запись количества символов
    std::cout<<std::endl;//производим действия клавиши Enter
}
 
//операция преобразования из объекта класса в float*
metring:: operator float*(void)
{
    char* ch_pt_temp ;//временный банк для обмена
    int isecondlen=2,//разряд числа
        idex=0;//индекс массива который представляет одно число
    bool flag= true;//флаг для разрешения выдиления памяти для ch_pt_temp
    
    //разбираем массив т.е. отдиляем числа от запятых, целые от вещественных
    for(int i = 0; i<strlen(ch_pt);i++)
    {
        if(flag)//выделяем каждый раз когда следует отдельное число 
        {
            ch_pt_temp = new char[isecondlen];//выделяю память под переменную для обмена
            ch_pt_temp[0]='\0';//принудительное указаник конца строки
            flag=false;//запрещаем перевыдиление памяти пока не закочится число
        }
        
        if(isecondlen>strlen(ch_pt_temp)&&(strlen(ch_pt_temp)!=0)&&ch_pt[i]!=',')
        {
            char* ch_pt_temp2 = new char[isecondlen+2];//выделяю память для временной переменной
            ch_pt_temp2[0]= '\0';//принудительно инициализирую её первый символ нулём
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt_temp2); i < strlen(ch_pt_temp)+1;i++,r++)
            {
                ch_pt_temp2[r]=ch_pt_temp[i];   
            }
            delete []ch_pt_temp;//освобождаю память
            //выделяю памяти больше на одну единицу
            ch_pt_temp = new char[isecondlen+2];//выделяю память под переменную для обмена
            ch_pt_temp[0]= '\0';//принудительно инициализирую её первый символ нулём
 
            //копируем сиволы в нашу строку с нулевым символом
            for(int i = 0, r = strlen(ch_pt_temp); i < strlen(ch_pt_temp2)+1;i++,r++)
            {
                ch_pt_temp[r]=ch_pt_temp2[i];   
            }
            delete []ch_pt_temp2;//освобождаю память
        }
        if(ch_pt[i]!=',')//если символ не является разделительным символом то просто копируем цифру
        {
            ch_pt_temp[idex++]=ch_pt[i];//копируем символ
            ch_pt_temp[idex]= '\0';//принудительное завершение строки
            isecondlen++;//увеличиваем разряд числа
        }
        if(ch_pt[i]==','||(i+1>=strlen(ch_pt)))//если символ разделительный то переобразуем массив ch_pt_temp в float
        {
            
            isecondlen=2;//инициализируем  флаг на 1 следящий за разрядом числа
            flag=true;//разрешаем перевыдиление памяти т.к. число закончилось
            if(imax_fmas)//если не нулевое значение значит нужно перевыделить память для вещественного массива
            {
                float* f_mas_temp = new float[imax_fmas];//создаю временный массив для страховки основного массива fmas
                for(int e =0 ; e<imax_fmas;e++)
                {
                    f_mas_temp[e]=fmas[e];//копирую значения массива
                }
                delete []fmas;//освобождаю память
                fmas = new float[imax_fmas+1];// перевыдиляю память
                for(int e =0 ; e<imax_fmas;e++)
                {
                    fmas[e]=f_mas_temp[e];//копирую значения массива
                }
                delete[]f_mas_temp;//освобождаю выделенную память
            }
            ch_pt_temp[idex]='\0';//принудительно завершаю строку нулевым символом
            idex = 0;//обнуление индекса
            //проверка числа т.е. было оно целым или вещественным путем поиска символа '.'
            for(int k = 0 ; k<strlen(ch_pt_temp);k++)
            {
                if(ch_pt_temp[k]=='.')//если такой символ есть то меняю его на ',' так требует atof
                {ch_pt_temp[k]=',';}
            }
 
            //преобразуем массив символов в вещественное число
            fmas[imax_fmas-1] = atof(ch_pt_temp);
            if(!(i+1>=strlen(ch_pt)))
            {imax_fmas++;}//увеличиваем число элементов в вещественном массиве
            delete[]ch_pt_temp;//освобождение памяти для массива для представления любого числа
        }
        
    }
    return (fmas);//возвращаю массив чисел типа float
}
//оператор для преобразования из объекта в массив символов
metring:: operator char*(void)
{ return (ch_pt); }
//возврат количества элементов в вещественном массиве
int metring:: return_imax_fmas(void)
{return(imax_fmas);}
/**************************************************************************************************************************************/
//класс издательство
class publication
{
    protected: 
        static const int sciMAX=100;//максимальный размер символьного массива
        metring* ch_name;//название
        float f_price;//цена
    public:
        //конструктор без параметров
        publication(void);
        //конструктор с двумя параметрами
        publication(char*, float);
        //конструктор копирования
        publication(publication&);
        //диструктор
        virtual~publication(void);
        //ввод данных
        virtual void put_into_the_class(void)=0;//чисто виртуальная фукция
        //вывод данных на экран консоли
        virtual void get_out_of_the_class(void);
        //оператор присвоения
        virtual publication& operator = (publication&);
};
publication::publication(char* ch_name, float f_price):f_price(f_price)
{
    setlocale(LC_ALL,"russian");//разрешаю вывод Русского языка
    publication::ch_name = new metring(ch_name);//выделяю память под строку и инициализирую массив переданным значением
}
publication::publication(void):f_price(0.0F)
{
    ch_name = new metring;//выделяю память под строку
    setlocale(LC_ALL,"russian");//разрешаю вывод Русского языка
}
//конструктор копирования
publication::publication(publication& val)
{
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса
}
//диструктор
publication::~publication(void)
{   if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
 
}//освобождение памяти, а точнее вызов диструктора строки 
//оператор присвоения
publication& publication:: operator = (publication& val)
{
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
}
//ввод данных
void publication:: put_into_the_class(void)
{
    std::cout<<"Введите название : ";
    ch_name->get_number();//получение от пользователя динамической строки символов
    std::cout<<"Введите цену : ";
    std::cin>>f_price;
}
//вывод данных на экран консоли
void publication:: get_out_of_the_class(void)
{
    std::cout<<"Название : "<<ch_name->ch_pt<<std::endl;
    std::cout<<"Цена : "<<f_price<<std::endl;
}
 
/*************************************************************************************************************/
//класс книга
class book : public publication
{
    private:
        int i_how_meny_pic;//количество страниц
    public:
        //конструктор без параметров
        book(void);
        //конструктор копирования
        book(book&);
        //конструктор с тремя параметрами
        book(int,char*,float);
        //ввод данных
        void put_into_the_class(void);
        //вывод данных на экран консоли
        void get_out_of_the_class(void);
        //операция присвоения
        book& operator = (book&);
};
//конструктор с тремя параметрами
book::book(int i_pictures,char* ch_name, float f_price) :i_how_meny_pic(i_pictures),publication(ch_name,f_price)
{setlocale(LC_ALL,"Russian");/*разрешаю вывод Русского языка*/}
//конструктор без параметров
book::book(void):publication(),i_how_meny_pic(0)
{setlocale(LC_ALL,"Russian");/*разрешаю вывод Русского языка*/}
//конструктор копирования
book::book(book& val)
{
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса   
    i_how_meny_pic = val.i_how_meny_pic;//копирую количество страниц в книге
}
//операция присвоения
book& book:: operator = (book& val)
{
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    i_how_meny_pic = val.i_how_meny_pic;//копирую количество страниц в книге
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
}
 
//ввод данных
void book:: put_into_the_class(void)
{
    publication::put_into_the_class();//вызов метода базового классa
    std::cout<<"Введите количество страниц : ";//получение количества страниц от пользователя
    std::cin>>i_how_meny_pic;
}
//вывод данных на экран консоли
void book:: get_out_of_the_class(void)
{
    publication::get_out_of_the_class();//вызов метода базового класса
    std::cout<<"Количество страниц : "<<i_how_meny_pic<<std::endl;//вывод на экран консоли значения кол-ва страниц
}
 
/*************************************************************************************************************/
//класс тип
class type : public publication
{
    private:
        float f_time;//время записи книги в менутах
    public:
        //конструктор без параметров
        type(void);
        //конструктор копирования
        type(type&);
        //конструктор с тремя параметрами
        type(float,char*,float);
        //ввод данных
        void put_into_the_class(void);
        //вывод данных на экран консоли
        void get_out_of_the_class(void);
        //оператор присваения
        type& operator = (type&);
 
};
//конструктор с тремя параметрами
type::type(float f_time,char* ch_name, float f_price) : publication(ch_name,f_price),f_time(f_time)
{setlocale(LC_ALL,"Russian");/*разрешаю вывод Русского языка*/}
//конструктор без параметров
type::type(void):publication(),f_time(0.0F)
{setlocale(LC_ALL,"Russian");/*разрешаю вывод Русского языка*/}
//конструктор копирования
type::type(type& val)
{
    ch_name = val.ch_name;//копирую указатель
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    f_price = val.f_price;//копирую другое поле класса   
    f_time = val.f_time;//коприрую время записи книги в минутах
}
//оператор присваения
type& type:: operator = (type& val)
{
    if(this == &val)//если объект присваивается сам себе то выход
    {return *this;}
    if(ch_name->icount==1)
    {delete ch_name;}//если больше ни кто ни указывает на эту строку то удаляем её
    else
    {ch_name->icount++;}//иначе именьшаем счётчик указателей на строку
    ch_name= val.ch_name;//копирую указатель
    f_price = val.f_price;//копирую другое поле класса
    f_time = val.f_time;//коприрую время записи книги в минутах
    ch_name->icount++;//увеличиваю счётчик указывающий на количество указателей на строку
    return *this;//возвращаю ссылку на объект
}
//ввод данных
void type:: put_into_the_class(void)
{
    publication::put_into_the_class();//вызов метода базового классa
    std::cout<<"Введите время записи книги в минутах : ";//получение времени записи от пользователя
    std::cin>>f_time;
}
//вывод данных на экран консоли
void type:: get_out_of_the_class(void)
{
    publication::get_out_of_the_class();//вызов метода базового класса
    std::cout<<"Время записи книги в минутах : "<<f_time<<std::endl;//вывод на экран консоли значения кол-ва страниц
}
 
/*************************************************************************************************************/
 int main(void)
 {
     std::string str_val;
     int ilenpublist=1;//длинна массива 
     int n=0;//счётчик элиметна массива
     class publication** publist = new publication*[ilenpublist];//указатель на базовый класс
     char ch_chose = 'd';//флаг для выхода из цикла
     do
     {
         ch_chose = 'd';//сброс флага
         if(n>=ilenpublist)//елси не хватает места для элементов в массиве то перевыделяем память
         {
            publication** temp = new publication*[ilenpublist];//временный массив для переброски данных
            for(int i =0 ; i<ilenpublist;i++)
            {   //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                if(dynamic_cast<book*>(*(publist+i)))
                {
                    *(temp+i) = new book;//выделяю память
                    //преобразую указатель на базовый класс на указатель на соответствующий производныый
                    *(dynamic_cast<book*>(*(temp+i)))=*(dynamic_cast<book*>(*(publist+i)));//побитовое копирование между объектами
                }
                //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                else if(dynamic_cast<type*>(*(publist+i)))
                {
                    
                    *(temp+i) = new type;//выделяю память
                    //преобразую указатель на базовый класс на указатель на соответствующий производныый
                    *(dynamic_cast<type*>(*(temp+i)))=*(dynamic_cast<type*>(*(publist+i)));//побитовое копирование между объектами
                }
            }
            //освобождаю память для перевыдиления
            for(int i =0 ; i<ilenpublist;i++)
            {delete publist[i];}
            //выделяю новый массив на один элемент больше чем предыдуший
            publist = new publication*[n+1];//указатель на базовый класс
            //возвращаю на место уже введеный данные пользователем
            for(int i=0;i<ilenpublist;i++)
            {   //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                if(dynamic_cast<book*>(*(temp+i)))
                {
                    *(publist+i) = new book;//выделяю память
                    //преобразую указатель на базовый класс на указатель на соответствующий производныый
                    *(dynamic_cast<book*>(*(publist+i)))=*(dynamic_cast<book*>(*(temp+i)));//побитовое копирование между объектами
                }
                //проверяю тип указателя и выделяю в новый временный массив соответствующую память
                else if(dynamic_cast<type*>(*(temp+i)))
                {
                    
                    *(publist+i) = new type;//выделяю память
                    //преобразую указатель на базовый класс на указатель на соответствующий производныый
                    *(dynamic_cast<type*>(*(publist+i)))=*(dynamic_cast<type*>(*(temp+i)));//побитовое копирование между объектами
                }
                
            }
            
            //освобождаю память из под временной переменной
            for(int i =0 ; i<ilenpublist;i++)
            {delete temp[i];}
            ilenpublist = n+1;//контроль реального количества элементов в массиве
         }
 
         while(1)//цикл для удачного ввода данных о типе книги
         {
            SYSTEMCRACH: //вернёмся сюда если пользователь ввел не правильный тип книги
            book::book();//вызов конструктора для разрешения русского языка
            std::cout<<"Выбирите тип книги audy или paper (a,p) :";
            std::cin>>str_val;
            if(str_val=="paper"||str_val == "p")
            {
                *(publist+n)=new book;//выделение памяти под необходимый производный класс
                (*(publist+n))->put_into_the_class();//взятие данный от пользователя
                n++;//увеличение счётчика элиментов массива
                break;//выход из внутреннего цикла
            }
            else if(str_val =="audy"||str_val == "a")//если ползователь ввел аудио книгу
            {
                *(publist+n)=new type;//выделение памяти под необходимый производный класс
                (*(publist+n))->put_into_the_class();//взятие данный от пользователя
                n++;//увеличение счётчика элиментов массива
                break;//выход из внутреннего цикла
            }
            else
            {
                std::cout<<"ОШИБКА не допустимый выбор! Попробуйте ещё раз!\n";
                goto SYSTEMCRACH;//переход в начало внутреннего цикла
            }
         }
         //опрос пользователя о продолжении цикла
         for(;ch_chose!='n' && ch_chose!='y';)//цикл законциться тогда когда пользователь введет y или n
         {
            std::cout<<"Продолжить ввод (y,n) : ";
            std::cin>>ch_chose;
            if(ch_chose!='n' && ch_chose!='y')
            {
                std::cout<<"Ошибка, Вы ввели не допустимый символ ("<<ch_chose
                      <<") попробуйте ещё раз!\n";
            }
         }
 
     }while(ch_chose!='n');
     //вывод данный на экран
     std::cout<<std::endl;
     for(int i =0;i<n;i++)
     {
        publist[i]->get_out_of_the_class();
     }
     //освобождаю память для перевыдиления
    for(int i =0 ; i<n;i++)
    {delete publist[i];}
     system ("pause");
 return 0;
 }
0
Жарю без масла
867 / 749 / 225
Регистрация: 13.01.2012
Сообщений: 1,702
11.02.2012, 18:10 17
Цитата Сообщение от stawerfar Посмотреть сообщение
На верно Вы правы, просто исходя из предыдущего опыта "выкладывания" всего кода - начинаются по моему не нужные разговоры которые просто уводят от темы. Ну например "божемой какой ужастный код",
"отвратительно" и т.д.. В ответ этому пишешь ребята "Вы себя нормально чувствуете?". А модератор посетивший чат не вникая в суть БАЦ - 30 ... балов.
не хочу вас расстраивать, но выложив сюда кучу обрывков кода вы нисколько не избавились от возможности таких разговоров. и кто нибудь может и напишет
Цитата Сообщение от stawerfar Посмотреть сообщение
"божемой какой ужастный код", "отвратительно" и т.д..
лучше выкладывать целиковую суть, и если "сути" много - выкладывать под катом
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
11.02.2012, 18:10 18
stawerfar, это не минимальный код. Минимальный код содержит только функционал, который позволяет повторить ошибку. Он не обязан пересекаться с изначальной задачей, главное - повторить ошибку. Например, если вопрос у вас был по операторам присваивания - вы должны были повторить вашу архитектуру классов, реализовав там только операторы присваивания (в которые, возможно, вставлены отладочные принты), и повторить в main'е только то место, которое вызывало у вас вопросы. Думаю, ваш код занял бы тогда строчек 40-50, и определить проблему было бы куда проще.
1
150 / 64 / 8
Регистрация: 14.12.2010
Сообщений: 347
Записей в блоге: 1
11.02.2012, 18:14  [ТС] 19
Большое спасибо я обязательно учту на будущее
0
11.02.2012, 18:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.02.2012, 18:14
Помогаю со студенческими работами здесь

Посмотрите описание конструктора копирования и оператора присваивания с ними все в порядке? После функции add теряются данные
class Person{ char *name; int age; char *floor; char *phone; public: Person(){...

В чём отличия конструктора копирования и конструктора перемещения? Где и как их нужно использовать?
Помогите разобраться в копирующем и перемещающем конструкторах. В чём их существенное отличие и...

Перегрузка присвоения
Вообщем, есть некий класс А, который хранит в себе массив: class A { private: int Arr;...

Нестандартное и полезное применение оператора присвоения
Подскажите, пожалуйста, когда полезно следующее использование оператора присвоения: (x = y) = w ?...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru