Главная страница
Навигация по странице:

  • Деструктор класса

  • Классы и структуры в среде Классы и структуры

  • Борис Пахомов Санкт Петербург бхв петербург 2013 удк 004. 4 Ббк 32. 973. 26018. 2 П


    Скачать 17.38 Mb.
    НазваниеБорис Пахомов Санкт Петербург бхв петербург 2013 удк 004. 4 Ббк 32. 973. 26018. 2 П
    АнкорMS Visual C.pdf
    Дата04.08.2018
    Размер17.38 Mb.
    Формат файлаpdf
    Имя файлаMS Visual C.pdf
    ТипДокументы
    #22453
    страница14 из 37
    1   ...   10   11   12   13   14   15   16   17   ...   37

    Полиморфизм
    Полиморфизм — это третий принцип, лежащий в основе создания класса. При полиморфизме (дословно многоформие) родственные объекты (те. происходящие от общего родителя) могут вести себя по-разному в зависимости от ситуации, возникающей в момент выполнения программы. Чтобы добиться полиморфизма, надо иметь возможность один и тот же метод в классе-родителе переопределить в клас- се-потомке. Например, все классы имеют общего прародителя — класс
    Object
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование В этом классе определен метод draw
    (рисовать фигуру. Классы, рисующие различные фигуры и произошедшие от
    Object
    — родственные классы. Каждый из них определяет рисование своей фигуры методом draw
    , унаследованным от
    Object
    : точку, линию, прямоугольник, окружность и т. д. Но все фигуры разные, хотя метод общий. Но этот метод draw в каждом из классов-потомков переопределен, те. в каждом классе-потомке ему назначена другая функциональность. Полиморфизм достигается за счет того, что методам из класса-родителя позволено выполняться в классе-потомке, а там оставляют только его имя, но при этом дают ему необходимую для данного класса функциональность. Такие методы должны объявляться в обоих классах с атрибутом virtual
    , записываемым перед атрибутом "возвращаемый тип данных. Если функция имеет атрибут virtual
    , то она может быть переопределена в классе-потомке, даже если количество и тип ее аргументов такие же, что и у функции базового класса. Переопределенная функция отменяет функцию базового класса. Кроме атрибута virtual
    , у методов существует атрибут friend
    . Методы с таким атрибутом, расположенным (как и атрибут virtual
    ) в объявлении метода перед указанием типа возвращаемых данных, называются дружественными. Метод, объявленный с атрибутом friend
    , имеет полный доступ к членам класса, расположенным в секциях private и protected
    , даже если этот метод — не член этого класса. Это справедливо и для классов внешний класс (те. его методы) имеет полный доступ к классу, который объявляет этот внешний класс дружественным. Во всех остальных аспектах дружественный метод — это обычный метод. Подобные методы из внешних классов, имея доступ к секциями, могут решать задачи, реализация которых с помощью методов-членов данного класса затруднительна или даже невозможна. Примеры создания классов

    Приведем пример двух программ, в которых объявлены и использованы простейшие классы. Пример Программа показана в листинге 8.2, результат работы программы — на рис. 8.2. Как работает программа, видно из строк комментария в телепрограммы. Листинг 8.2

    //8.1_2011.cpp
    #include "stdafx.h"
    #include
    #include using namespace System;

    148 Часть
    I. Изучение языка С/С++
    class A
    { protected: int x; к этим данным имеют доступ только методы данного класса и производных int y; public: int a; int b; int f1(int x, int y) метод класса
    { return(x-y);
    }
    }; class B : A это объявляется класс, производный от А
    { при этом наследуются члены класса А public: int f2(int x) метод класса
    {
    A::x=20; /* здесь могут использоваться члены-данные базового класса из секции protected. Так как имя аргумента метода f2() совпадает с именем полях из класса А, унаследованного классом В, то чтобы различить, какая переменная к какому классу относится, потребовалось уточнить с помощью спецификатора ::. Показано, что в теле методах берется тот, что унаследован от Аи собственный аргумент х самого метода f2(): */ return(x+A::x); возврат суммы x из B и x из А
    }
    }; int main(int argc, char* argv[])
    {
    A min; создание экземпляров классов A, B
    B max; min.a=10; Работа с элементами класса А из секции public min.b=20; int x1=min.f1(min.a,min.b); int x2=max.f2(10); // Работа с элементом класса B printf("x1=%d\nx2= %d\n",x1,x2);
    _getch();
    } Обратите внимание, что когда вы создаете переменную типа класса, те. экземпляр класса (например,
    A min;
    , где min
    — экземпляр класса, то для этого экземпляра никакой памяти не выделяете, а компилятор все-таки размещает этот экземпляр где-то в памяти. Почему
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование Рис 8.2. Результат работы программы листинга Среда исполнения приложений в С/С++ выделяет два вида памяти статическую и динамическую. Последняя носит название "куча. Куча может быть управляемой и неуправляемой. Если компилятор способен определить размер памяти под объявленную переменную, то он выделяет для нее место в статической памяти (например, под переменную типа int он выделит 4 байта, а под массив типа int из 10 элементов он выделит 40 байтов. Если же компилятор не в состоянии определить размер памяти под объявленную переменную, то он потребует от программиста поместить такую переменную в куче в динамической памяти. Кстати, если программист сам хочет работать с динамической памятью (даже когда компилятор может поместить переменную в статической памяти, то язык это ему позволяет. Для простых переменных при этом используются функция malloc()
    , которая выделяет область памяти в динамической области и возвращает указатель на эту область, и функция free()
    , которая освобождает занятую переменной область и передает освобожденную память в общее пользование. Если же работа происходит с объектами, то здесь используются операторы new
    — аналоги аналог free()
    . Указанные функции и аналогичные им операторы работают с неуправляемой кучей. С управляемой кучей работает утилита, и нет необходимости освобождать самому память от объекта, поскольку в этом случае работает так называемая автоматическая сборка мусора когда объект становится ненужным, память от него освобождается. Чтобы работать с такой кучей, надо перейти в режим CLR. Что касается вопроса "почему, то очевидно, что компилятор размещает переменную типа класса, объявленного нами, в статической области памяти. Но приведем пример этой же программы, в которой используется по нашему желанию) динамическая память (мы, естественно, приводим только тело функции main()
    , где это отражается. int main()
    {
    A *min =(A *) new A(); создание экземпляров классов A, B
    B *max= (B *) new B();
    min->a=10; Работа с элементами класса А из секции public min->b=20;
    int x1=min->f1(min->a,min->b);
    int x2=max->f2(10); // Работа с элементом класса B
    printf("x1=%d\nx2= %d\n",x1,x2);
    _getch();

    150 Часть
    I. Изучение языка С/С++
    delete min;
    delete В данном случае оператор new размещает объект в куче, выдает адрес этого объекта, а конструктор инициализирует объект. Пример Создадим класс, членами которого будут изделия, состоящие из деталей и их стои- мостей, а также методы, первый из которых присваивает значения изделию, детали и стоимости через свои параметры, а второй выводит на экран значения, присвоенные первым методом. Текст программы приведен в листинге 8.3, результат работы программы представлен на рис. 8.3. Листинг 8.3
    //8.2_2011.cpp
    #include "stdafx.h"
    #include для printf()
    #include для _getch() using namespace System; class produce начало определения класса
    { private: поля класса int modelnumber; номер изделия int partnumber; номер детали float cost; стоимость детали public: установка данных с помощью метода присваивает данным класса значения своих параметров void setpart(int mn, int pn, float c)
    { modelnumber = mn; partnumber = pn; cost = c;
    } void show() вывод данных
    { printf("The Number of the Model is %d\n",modelnumber); printf("The Number of the Part is %d\n",partnumber); printf("The Cost of the Part is %.2f\n",cost);
    }
    }; конец описания класса
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование обработка класса в головной программе int main()
    { produce izd; определение объекта из класса (экземпляр класса) izd.setpart(100, 200, 250.5); вызов метода класса izd.show(); вывод данных
    _getch();
    } Рис 8.3. Результат работы программы листинга Этот небольшой созданный нами класс позволяет выводить на экран характеристики изделия, описанного в нем. Пример Используем класс, созданный в примере 2, для создания нового класса — наследника класса из примера 2. Новый класс должен будет задавать дополнительную характеристику изделия — его форму. Пример программы приведен в листинге 8.4, результат работы программы — на рис. 8.4. Листинг 8.4
    // 8.3_2011.cpp
    #include "stdafx.h"
    #include для printf()
    #include для _getch() using namespace System; детали изделия в качестве объектов (экземпляров класса) class produce начало определения класса
    { private: int modelnumber; номер изделия int partnumber; номер детали float cost; стоимость детали public: установка данных
    //функция-член класса присваивает данным класса значения своих параметров

    152 Часть
    I. Изучение языка С/С++
    void setpart(int mn, int pn, float c)
    { modelnumber = mn; partnumber = pn; cost = c;
    } void show() вывод данных
    { printf("The Number of the Model is %d\n",modelnumber); printf("The Number of the Part is %d\n",partnumber); printf("The Cost of the Part is %.2f\n",cost);
    }
    }; объявление класса-наследника с новыми членами class MoreProduce : public produce
    { public: char *ProduceForm; описание формы изделия void FormDecl(char *s)
    {
    ProduceForm=s;
    } void show1()
    { printf("The ProduceForm is %s\n",ProduceForm);
    }
    }; обработка класса в головной программе int main()
    {
    MoreProduce newizd; newizd.setpart(100,200,250.5); newizd.FormDecl("Square"); newizd.show(); newizd.show1();
    _getch();
    } Рис 8.4. Результат работы программы листинга 8.4
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование Конструктор класса
    Конструктор класса тоже член класса, но специфический — это метод с таким же именем, что и класс. Такие методы не имеют право возвращать какие-либо значения если вы написали в конструкторе оператор return
    , компилятор выдаст ошибку. Конструктор выполняет различные задачи и невиден вам как программисту. Даже если вы сами не писали его текст, конструктор по умолчанию всегда присутствует в классе, ибо основная его задача — создавать в памяти экземпляр класса (те. как бы по проекту (классу) построить дом (экземпляр класса. В этом случае конструктор берется из общего прародителя классов — класса
    Object
    , в котором он имеется. Вторая задача конструктора — придавать всем членам-данным класса начальные значения — инициализировать класс. Если вы сами не построили конструктор, который станет инициализировать члены-данные вашего класса вашими же значениями, то этим данным невидимый для вас конструктор (конструктор по умолчанию) придаст свои, принятые в системе для данного типа величин значения (например, данные типа int получат нулевые значения и т. д. В листинге 8.5 приведен пример класса с конструктором, созданным для инициализации членов-данных класса теми значениями, которые задаст пользователь класса при работе с ним. Листинг 8.5
    // 8.4_2011.cpp
    #include "stdafx.h"
    #include для printf()
    #include для _getch() using namespace System; class Date
    { public: Это члены-данные класса. Сними будут работать функции-члены класса get... и set...*/ int month; int day; int year;
    Date( int dy, int mn, int yr конструктор класса
    {
    /*члены-данные day, month, year будут принимать значения, которые поступят в конструктор как в функцию при его использовании где-нибудь в приложении day=dy; month=mn; year=yr;
    }

    154 Часть
    I. Изучение языка С/С++
    //внешние функции класса int getMonth() const; это только прототип функции – информация для компилятора Функция getMonth() объявлена с атрибутом const — может данные только поставлять, не изменяя их (read-only), а функция setMonth() не имеет квалификатора const и поэтому данные внутри себя может изменять виды функций определены вне класса (см. ниже void setMonth(int mn ); это только прототип функции — информация для компилятора
    // методы класса int getDay(); void setDay(int dy); int getYear(); void setYear(int yr);

    Date()//Деструктор класса
    {
    }
    }; конец описания класса
    /* создание функций (вне класса, поэтому надо указывать имя класса, для которого эти функции создаются int Date::getMonth() const функция для класса Date
    { return month; функция ничего не изменяет
    }
    //------------------ void Date::setMonth(int mn )
    { month = mn; Функция изменяет член-данное класса
    }
    //----------------------- int Date::getDay()
    { return Date::day;
    }
    //--------------------------- void Date::setDay(int dy )
    { day = dy;
    }
    //------------------------- int Date::getYear()
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование
    { return Date::year;
    }
    //--------------------------------- void Date::setYear(int yr )
    {
    Date::year = yr;
    }
    //======================================================== int main() Работа с созданным классом
    { здесь с помощью конструктора в экземпляре класса (экземпляр с именем MyDate) устанавливаются заданные пользователем значения
    Date MyDate(12,3,2012); здесь определяется и инициализируется
    экземпляр MyDate класса Date int d,m,y; d=MyDate.getDay(); //d=12 m=MyDate.getMonth(); //m=3 y=MyDate.getYear(); //y=2012 printf("d=%d, m=%d, y=%d\n",d,m,y);
    Date BirthDate ( 1, 12, 1938 ); изменить значение месяца назначение в экземпляре MyDate:*/
    MyDate.setMonth( 4 ); m=MyDate.getMonth(); // m=4 изменить значение месяца назначение в экземпляре BirthDate: */
    BirthDate.setMonth( 5 ); m=BirthDate.getMonth(); //m=5
    _getch();
    } Результат работы приложения показан на рис. 8.5. Рис 8.5. Работа конструктора класса
    Заметим, что у класса может быть много конструкторов. Когда создается класс, то для инициализации его различных полей и создаются различные конструкторы. Хотя все они имеют одинаковое имя, совпадающее с именем класса, тем не менее компилятор их различает по различным наборам параметров и типов.

    156 Часть
    I. Изучение языка С/С++
    Деструктор класса
    Суть этой функции обратная сути функции конструктора. Она призвана разрушить созданный конструктором экземпляр класса и освободить от него память. Имя де- структора совпадает с именем класса, но перед именем указывается знак "тильда"
    (

    ). Для предыдущего примера деструктор будет иметь вид
    Date()
    . Деструктор у класса должен быть один, в то время как конструкторов может быть много.
    Классы
    и
    структуры в среде Классы и структуры
    Наряду с обычными классами и структурами (их еще называют классы и структуры или "родные, существуют классы и структуры для работы в среде (их еще называют классы (управляемые классы) и структуры (управляемые структуры. Эти конструкции будут располагаться в выделенной средой CLR памяти, и поэтому приложения с применением этого типа выделенной памяти должны компилироваться с ключом
    /clr
    . Напомним, что в версии среды 2011 консольные приложения строятся по шаблону сразу с ключом
    /clr
    . Приложения типа Windows Form этому условию удовлетворяют (мы их рассмотрим позже. Напомним также, что объекты, попадающие в память под управлением CLR, требуют в программе специального выделения памяти, т. кони должны попасть на самом деле в динамическую память. Мы уже знаем, что указатели на такую управляемую память обозначаются символом '^'
    . Выделяют такую память с помощью утилиты gcnew. Структуры и классы для работы в режиме CLR могут быть ссылочного типа (перед именем класса или структуры стоит квалификатор ref
    ) и типа "значение" (перед именем класса или структуры стоит квалификатор value
    ). При объявлении такой конструкции первым квалификатором идет квалификатор доступа к данной конструкции. Для класса по умолчанию идет квалификатор private
    , а для структуры — public
    , что также имеет место и для эквивалентов этих конструкций в режиме native это для предыдущих версий среды. В чем смысл этих конструкций Например, возьмем классы ref class MyClass
    {
    public:
    int m_i;
    };
    value class MyClassV
    {
    public:
    int m_i;
    };
    Глава
    8. Классы в С.
    Объектно
    -
    ориентированное программирование Это обычные классы, только атрибут ref указывает, что его класс надо размещать в управляемой куче. Например
    MyClass ^mc = gcnew Здесь gcnew для экземпляра класса выделяет память и размещает объект в куче и выдает указатель mc на начало объекта. Если же попробовать объект разместить в куче, то компилятор выдаст ошибку. А для класса с атрибутом value компилятор разрешает это делать, те. оператор
    MyClassV *vv=new MyClassV(); срабатывает. Пример int main() Головная функция {
    MyClass ^mc = gcnew идет // MyClass *mc=new не идет mc->m_i=111; присвоили значение члену класса int mci=mc->m_i; достали значение из класса //MyClassV ^vv=gcnew MyClassV(); идет MyClassV *vv=new MyClassV(); идет vv->m_i=222;
    int mv=vv->m_i;
    Console::WriteLine("mci=" + mci + " mv= " + mv);
    delete vv; сами должны удалять объект из кучи
    }
    Результат: mci=111 и mv= Оказывается, что можно ссылаться из типа на тип. Например, функция в типе (классе или структуре) может принимать параметр например, struct
    ). При этом если тип и функция имеют атрибут доступа public
    , то и тип должен иметь атрибут Например include "stdafx.h"
    using namespace тип public struct N
    {
    int i;
    };
    public ref struct R тип // функция, у которой параметр nn имеет тип N,
    те. параметр – структура

    158 Часть
    I. Изучение языка С/С++
    int f(N nn)
    {
    nn.i++;
    return(nn.i);
    }
    };
    int main() Головная функция {
    R ^r = gcnew R;
    N n;
    n.i=333;
    int ni=r->f(n);
    Console::WriteLine("ni=" + Абстрактные классы
    Методы класса могут быть объявлены как абстрактные. Это означает, что в этом классе нет реализации этих методов. Абстрактные методы пишутся с модификатором. Класс, в котором есть хотя бы один абстрактный метод, называется
    абстрактным (в таком классе могут быть и обычные методы. Нельзя создавать экземпляры абстрактного класса — такой класс может использоваться только в качестве базового класса для других классов. Для потомка такого класса есть две возможности или он реализует все абстрактные методы базового класса (ив этом случае для такого класса-потомка мы сможем создавать его экземпляры, или он реализует не все абстрактные методы базового класса (в этом случае он остается тоже абстрактным классом и единственная возможность его использования — производить от него классы-потомки). Статические функции
    1   ...   10   11   12   13   14   15   16   17   ...   37


    написать администратору сайта