Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

техпрог / Comp-Sci-08

.pdf
Скачиваний:
45
Добавлен:
10.02.2015
Размер:
719.97 Кб
Скачать

Материалы к лекции 8

Объектно-ориентированное программирование

Наследование. Продолжение

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

Пример. Что будет напечатано при вызове программы

#include <iostream> using namespace std; class base {

public:

base() { cout << " constructor base class \n"; } ~base() { cout << " destructor base class \n"; }

};

class derived : public base { public:

derived() { cout << " constructor derived class \n"; } ~derived() { cout << " destructor derived class \n"; }

};

int main()

{derived ob; return 0;

}

Пример. Передача параметров в базовый класс. Что будет напечатано при вызове программы

#include <iostream> using namespace std; class base { private:

int i; public:

base(int n) {

cout << " constructor base class \n"; i = n;

}

~base() { cout << " destructor base class \n"; } void showi() { cout << i << '\n'; }

};

class derived : public base { int j;

public:

derived(int n, int m) : base(m) {/*передача аргумента в базовый класс */ cout << " constructor derived class \n";

j = n;

}

~derived() { cout << " destructor derived class\n"; } void showj() { cout << j << '\n'; }

};

int main()

{derived ob(10, 20); ob.showi(); ob.showj();

return 0;

}

Диаграмма классов

Пример.

// Students.cpp :

//

#include "stdafx.h" #include <iostream> #include <string> using namespace std;

class Person{ protected:

string name;//Имя string fam;// Фамилия

public: Person(){name="Ivan";fam="Petrov";}

Person(string s,string f){name=s;fam=f;} ~Person(){cout<<"\nPerson Destructor";} void set_name(string s){name=s;}

string get_name() {return name;} void set_fam(string f){fam=f;} string get_fam(){return fam;}

};

class Student: public Person { int curs;//курс

public: Student(){name="Ivan";fam="Petrov";curs=2;}

Student(string s,string f,int k):Person(s,f){curs=k;}

~Student(){cout<<"\nStudent Destructor";} void set_curs(int k){curs=k;}

int get_curs() {return curs;}

};

int _tmain(int argc, _TCHAR* argv[])

{

Person man("Petr","Ivanov"); cout<<"\n"<<man.get_fam(); Student st("Alex","Vasilev",2);

cout<<"\n"<<st.get_fam()<<st.get_name(); return 0;

}

Диаграмму классов можно получить в Visual Studio

Можно вывести детали

С помощью

Создаем диаграмму классов

Пример. Из С. Прата. Язык программирования C++, стр. 608, 614. На стр. 616 – особые связи производного класса с базовым. В примере перечисление enum используется для определения константы. О перечислениях подробнее см. стр. 148-151. О константах в классе см.

стр. 471.

#include <iostream> #include <cstring> using namespace std; class TableTennisPlayer

{

private:

enum {LIM = 20}; char firstname[LIM]; char lastname[LIM]; bool hasTable;

public:

TableTennisPlayer (const char * fn = "none",

const char * ln = "none", bool ht = false);

void Name() const;

bool HasTable() const { return hasTable; } ; void ResetTable(bool v) { hasTable = v; };

};

class RatedPlayer : public TableTennisPlayer

{

private:

unsigned int rating; public:

RatedPlayer (unsigned int r = 0, const char * fn = "none",

const char * ln = "none", bool ht = false); RatedPlayer(unsigned int r, const TableTennisPlayer & tp);

unsigned int Rating() { return rating; }

void ResetRating (unsigned int r) {rating = r;}

};

TableTennisPlayer::TableTennisPlayer (const char * fn, const char * ln, bool ht)

{strncpy(firstname, fn, LIM - 1); firstname[LIM - 1] = '\0'; strncpy(lastname, ln, LIM - 1); lastname[LIM - 1] = '\0';

hasTable = ht;

}

void TableTennisPlayer::Name() const

{cout << lastname << ", " << firstname;} RatedPlayer::RatedPlayer(unsigned int r, const char * fn,

const char * ln, bool ht) : TableTennisPlayer(fn, ln, ht)

{rating = r;}

RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp) : TableTennisPlayer(tp), rating(r)

{

}

int main ( void )

{TableTennisPlayer player1("Timur", "Kazan", false); RatedPlayer rplayer1(1140, "Marat", "Samara", true);

rplayer1.Name(); // наследник использует метод базового класса if (rplayer1.HasTable()) cout << ": has a table.\n";

else cout << ": hasn't a table.\n";

player1.Name(); // базовый объект использует метод базового класса if (player1.HasTable()) cout << ": has a table";

else cout << ": hasn't a table.\n"; cout << "Name: ";

rplayer1.Name();

cout << "; Rating: " << rplayer1.Rating() << endl;

RatedPlayer rplayer2(1212, player1); //создан вторым конструктором cout << "Name: ";

rplayer2.Name();

cout << "; Rating: " << rplayer2.Rating() << endl; // код из замечания

return 0;

}

Замечание. Указатель базового класса может указывать на производный объект без явного преобразования типов. Ссылка на базовый объект может указывать на производный объект без явного преобразования типов. Например, можем добавить следующий код

TableTennisPlayer player1("Timur", "Kazan", false); RatedPlayer rplayer1(1140, "Marat", "Samara", true);

RatedPlayer rplayer2(1212, player1); TableTennisPlayer & rt=rplayer1; TableTennisPlayer * pt=&rplayer2; rt.Name();

pt->Name();

Присваивать объекты и адреса базовых классов ссылкам и указателям производных классов нельзя. Например, следующие операторы ошибочны

RatedPlayer &rr=player1;

RatedPlayer *pr=&player1;

Но можно поправить дело с помощью приведения типов (хотя это не рекомендуется)

RatedPlayer &rr=(RatedPlayer&)player1; RatedPlayer *pr=(RatedPlayer*)&player1;

Правила области действия и разрешение имен при наследовании. Перегрузка и сокрытие имен. Вызов метода базового класса, скрытого производным классом

Пример. Перекрытия

#include <iostream> using namespace std;

class Base { protected:

int x; public:

int get_x(){cout<<"Base get ";return x;} void set_x(int xa){cout<<"Base set ";x=xa;}

};

class Derived:public Base{ int x;

public:

int get_x(){cout<<"Derived get ";return x;}; void set_x(int xa){cout<<" Derived set ";x=xa;} void ff()

{int x=5;

cout<<"\n ff() x= "<<x<<"\n"; cout<<"\n Base x"<<Base::x; cout<<"\n Derived x"<<Derived::x;

}

};

int x=900; int main()

{ int x=500; Base Bob1;

Bob1.set_x(100); Derived Dob1;

Dob1.set_x(300); Dob1.Base::set_x(999); x=Bob1.get_x(); cout<<"\nBob1 x= "<<x; x=Dob1.get_x(); cout<<"\nDob1 x= "<<x; Dob1.ff();

cout<<"\n ::x="<<::x; return 0;

}

Поясняющая картинка.

Base:

Derived:

 

 

 

 

 

Base::x

 

Base::x

 

 

 

Derived::x

 

Base::get_x()

 

 

 

 

 

 

Base::set_x()

 

Base::get_x()

 

 

 

Base::set_x()

 

 

 

Derived::get_x()

 

 

 

 

 

 

Derived::set_x()

 

 

 

Derived::ff()

 

 

 

 

Соседние файлы в папке техпрог