Kody programów demonstrowanych na wykładzie:
Wyjątki
Program #1
Podgladanie.h
#pragma once
#include <iostream>
using namespace std;
class Podgladanie
{
public:
Podgladanie(void) {
cout << "Podgladanie()"<< endl;
};
~Podgladanie(void) {
cout << "~Podgladanie()"<< endl;
};
};
main.cpp
#include <iostream>
#include "Podgladanie.h"
using namespace std;
void przezDziurkeOdKlucza() {
Podgladanie P;
for(int i = 0; i < 3; i++)
cout <<"Nic nie widzę."<< endl;
throw 47;
}
int main() {
try {
cout << "I co? widzisz coś?..." << endl;
przezDziurkeOdKlucza();
} catch(int) {
cout << "To daj też popatrzeć." << endl;
}
return 0;
}
Program #2
#include <iostream>
using namespace std;
class Brzoskwinia {
public:
class Pestka {};
class Mala : public Pestka {};
class Duza : public Pestka {};
void scisk() { throw Duza(); }
};
int main() {
Brzoskwinia b;
try {
b.scisk();
}
catch(Brzoskwinia::Mala&) { // nigdy nie zostanie wywołany..
cout << "Mala Pestka schwytana" << endl;
}
catch(Brzoskwinia::Duza&) { // .. a ten tak.
cout << "Duza Pestka schwytana" << endl;
}
catch (Brzoskwinia::Pestka&) { // ten jest tylko pro forma.
cout << "zlapalem, co akurat lecialo.." << endl;
};
return 0;
}
Program #3
#include<exception>
#include<iostream>
using namespace std;
void nowe_zakonczenie( ) {
cout << "Ja tu wroce.." << endl;
exit(0);
};
void (*wf)() = set_terminate(nowe_zakonczenie);
class Fuszerka {
public:
class Owoc {};
void f() {
cout << "Fuszerka ::f()" << endl;
throw Owoc();
};
Fuszerka() { };
~Fuszerka() {
throw 'c';
};
};
int main() {
try {
Fuszerka b;
b.f();
} catch(...) {
cout << "zlapalem cos.." << endl;
}
return 0;
}
Program #4
#include<exception>
#include<iostream>
using namespace std;
class Trace {
static int counter;
int objid;
public:
Trace() {
objid = counter++;
cout << "konstruktor Trace #" << objid << endl;
if(objid == 3) throw 3;
}
~Trace() {
cout << "destruktor Trace #" << objid << endl;
}
};
int Trace::counter = 0;
int main() {
try {
Trace array[5];
} catch(int i) {
cout << "przechwycono " << i << endl;
}
return 0;
}
Program #5
#include <cstdio>
#include<cstring>
#include <iostream>
using namespace std;
class mem
{
char * pdata;
public:
mem(unsigned int size=0);
~mem() { delete [] pdata; }
void alloc(unsigned int size);
char* getbuffer() const { return pdata; };
};
mem::mem(unsigned int size)
{
if (size)
pdata = new char[size];
else pdata=0;
};
void mem::alloc(unsigned int size)
{
if (pdata)
return;
pdata = new char[size];
};
int main() {
mem bufor(100);
strcpy(bufor.getbuffer(),"Taki sobie napis");
cout << bufor.getbuffer() << endl;
return 0;
}
Cechy charakterystyczne
#include<iostream>
using namespace std;
class Milk {
public:
friend ostream& operator<<(ostream& os, const Milk&) {
return os << "Mleko";
}
};
class CondensedMilk {
public:
friend ostream& operator<<(ostream& os, const CondensedMilk &) {
return os << "Skondensowane Mleko";
}
};
class Honey {
public:
friend ostream& operator<<(ostream& os, const Honey&) {
return os << "Miodek";
}
};
class Cookies {
public:
friend ostream& operator<<(ostream& os, const Cookies&) {
return os << "Ciasteczka";
}
};
class Bear {
public:
friend ostream& operator<<(ostream& os, const Bear&) {
return os << "Puchatek";
}
};
class Boy {
public:
friend ostream& operator<<(ostream& os, const Boy&) {
return os << "Krzyś";
}
};
// bazowy szablon cech (pusty, może opisywać cechy wspólne)
template<class Guest>
class GuestTraits { };
// Cechy charakterystyczne – specjalizacje typu Guest:
// Specjalizacja dla misia
template<> class GuestTraits<Bear> {
public:
typedef CondensedMilk beverage_type;
typedef Honey snack_type;
};
// specjalizacja dla chłopca
template<> class GuestTraits<Boy> {
public:
typedef Milk beverage_type;
typedef Cookies snack_type;
};
// specjalizacja mieszana
class MixedUpTraits {
public:
typedef Milk beverage_type;
typedef Honey snack_type;
};
// Szablon Guest – korzysta z klasy cech
template<class Guest, class traits = GuestTraits<Guest> >
class BearCorner {
Guest theGuest;
typedef typename traits::beverage_type beverage_type;
typedef typename traits::snack_type snack_type;
beverage_type bev;
snack_type snack;
public:
BearCorner(const Guest& g) : theGuest(g) {}
void entertain() {
cout << "Wchodzi " << theGuest
<< " podajemy " << bev
<< " i " << snack << endl;
}
};
int main() {
Boy cr;
BearCorner<Boy> pc1(cr);
pc1.entertain();
Bear pb;
BearCorner<Bear> pc2(pb);
pc2.entertain();
BearCorner<Bear, MixedUpTraits> pc3(pb);
pc3.entertain();
}
Domieszkowanie klas
#include <string>
#include <ctime>
#include <iostream>
using namespace std;
// klasa reprezentująca prosty stoper
class Timer {
time_t start, finish;
public:
Timer() {
Reset();
}
double GetElapsedTimeSecs() {
time(&finish);
return difftime(finish, start);
}
void Reset() {
time(&start);
}
};
// Domieszka #1: Zapisywanie komunikatów o rozpoczęciu i zakończeniu zadania
template< class T >
class LoggingTask : public T {
public:
void Execute() {
std::cout << "LOG: The task is starting - " <<
T::GetName().c_str() << std::endl;
T::Execute();
std::cout << "LOG: The task has completed - " <<
T::GetName().c_str() << std::endl;
}
};
// Domieszka #2: Zapisywanie czasu wykonania zadania
template< class T >
class TimingTask : public T
{
Timer timer_;
public:
void Execute() {
timer_.Reset();
T::Execute();
double t = timer_.GetElapsedTimeSecs();
std::cout << "Task Duration: " << t << " seconds" << std::endl;
}
};
// Klasa implementująca właściwą czynność realizowaną przez to zadanie
class MyTask {
public:
virtual void Execute() {
std::cout << "...This is where the task is executed..." << std::endl;
// ... wykonanie zadania
}
virtual std::string GetName() {
return "My task name";
}
};
/*
Klasy TimingTask oraz LoggingTask są klasami - domieszkami.
Klasa MyTask reprezentuje jedno konkretne zadanie (w przeciwieństwie do domieszek, które
mają charakter uniwersalny, ponieważ muszą znaleźć zastosowanie w wielu miejscach kodu).
*/
// korzystanie z klas
int main() {
MyTask t1; // Obiekt reprezentujący zadanie
t1.Execute();
TimingTask< MyTask > t2; // Obiekt reprezentujący zadanie domieszkowane pomiarem czasu
t2.Execute();
LoggingTask< TimingTask< MyTask > > t3; // Obiekt reprezentujący zadanie domieszkowane logowaniem i pomiarem czasu
t3.Execute();
// Obiekt reprezentujący zadanie domieszkowane pomiarem czasu i logowaniem
typedef TimingTask<LoggingTask<MyTask>> Task;
Task t4;
t4.Execute();
}
STL – kontenery
Iteratory i wskaźnik względny do metody
#include <vector>
#include <iostream>
using namespace std;
class Z {
int i;
public:
Z(int ii) : i(ii) {}
void g() { ++i; }
friend ostream& operator<<(
ostream& os, const Z& z);
};
ostream& operator<<(ostream& os, const Z& z) {
return os << z.i;
}
template<typename Cont, typename PtrMemFun>
void apply(Cont& c, PtrMemFun f) {
typename Cont::iterator it = c.begin();
while (it != c.end()) {
((*it).*f)();
++it;
}
}
//Przykład zastosowania "apply"
int main() {
vector<Z> vz;
// zapełniamy wektor
for (int i = 0; i < 10; i++)
vz.push_back(Z(i));
// wysyłamy wektor do strumienia cout
for (vector<Z>::iterator j = vz.begin(); j != vz.end(); ++j)
cout << *j << " ";
cout << endl;
// wykorzystujemy szablon apply
apply(vz, &Z::g);
// ponownie wysyłamy wektor do cout
for (vector<Z>::iterator j = vz.begin(); j != vz.end(); ++j)
cout << *j << " ";
cout << endl;
system("pause");
}
vector
– przykład użycia #2
FileEditor.h
#pragma once
#include <vector>
#include <string>
#include <iostream>
using namespace std;
class FileEditor: public vector<std::string>
{
public:
void open(const char* filename);
FileEditor(const char* filename) {
open(filename);
};
FileEditor() {};
void write(ostream& out = cout);
};
FileEditor.cpp
#include "FileEditor.h"
#include <fstream>
void FileEditor::open(const char* filename) {
ifstream in(filename);
string line;
while (getline(in, line))
push_back(line);
}
void FileEditor::write(ostream& out) {
for (iterator w = begin(); w != end(); w++)
out << *w << endl;
}
main.cpp
#include "FileEditor.h"
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
FileEditor file;
if (argc > 1) {
file.open(argv[1]);
}
else {
file.open("plik-testowy.txt");
}
int i = 1;
FileEditor::iterator w = file.begin();
while (w != file.end()) {
ostringstream ss;
ss << i++;
*w = ss.str() + ": " + *w; // dopisanie numeru na początku wiersza
++w;
}
file.write(cout);
system("pause");
}
map
– przykład użycia
#include <map>
#include <iostream>
#include <string>
using namespace std;
class Student {
string Nazwisko;
int Wiek;
public:
Student() : Nazwisko("Nowy student"), Wiek(19) {};
Student(const string& nazwisko, const int wiek) :
Nazwisko(nazwisko), Wiek(wiek) {};
Student(const Student& temp) :
Nazwisko(temp.PobierzNazwisko()), Wiek(temp.PobierzWiek()) {};
~Student() {};
void UstawNazwisko(const string& nazwisko) { Nazwisko = nazwisko; };
string PobierzNazwisko() const { return Nazwisko; };
void UstawWiek(const int wiek) { Wiek = wiek; };
int PobierzWiek() const { return Wiek; };
Student& operator=(const Student& temp);
};
Student& Student::operator=(const Student& temp) {
Nazwisko = temp.PobierzNazwisko();
Wiek = temp.PobierzWiek();
return *this;
};
ostream& operator<<(ostream& osoba, const Student& temp) {
osoba << temp.PobierzNazwisko() << " ma " << temp.PobierzWiek() << " lat";
return osoba;
};
template<typename T, typename A>
void ShowMap(const map<T, A>& v) {
for (typename map<T, A>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << i->first << ": " << i->second << "\n";
cout << endl;
};
typedef map<string, Student> Studenci; //Studenci – mapa elementów
int main() {
Student Kowalski("Kowalski", 19);
Student Nowak("Nowak", 20);
Student Adamczewski("Adamczewski", 21);
Student Kowalczyk("Kowalczyk", 16);
Studenci Rocznik;
// dodajemy nowe elementy i nadajemy im wartości
Rocznik[Kowalski.PobierzNazwisko()] = Kowalski;
Rocznik[Nowak.PobierzNazwisko()] = Nowak;
Rocznik[Adamczewski.PobierzNazwisko()] = Adamczewski;
Rocznik[Kowalczyk.PobierzNazwisko()] = Kowalczyk;
cout << "Rocznik:\n";
ShowMap(Rocznik);
// próba odwołania się do nieistniejącego klucza bez przypisania wartości
cout << "Wiemy że " << Rocznik["Zeromski"].PobierzNazwisko()
<< " ma " << Rocznik["Zeromski"].PobierzWiek() << " lat\n";
system("pause");
};