A követelmények és pár mintafeladat a http://www.eet.bme.hu/vieea026/HF/ oldalon találhatók. A feladat szabadon választott, tehát örülünk, ha valaki saját feladatot hoz.
Megjegyzések az oldalon felsorolt követelményekkel kapcsolatban (ezek a megjegyzések csak a saját csoportomban érvényesek):
Tagfüggvénnyel csak akkor valósítható meg egy kétoperandusú m velet, ha az operátortól balra saját objektum áll, mert annak az objektumnak lesz a megvalósított operátor a tagfüggvénye. Nézzük meg, milyen lehet ségeink vannak Vec2D objektum és valós szám szorzására!
a) Vec2D * double. Itt a *-tól balra saját objektum áll, ennek tagfüggvényeként megvalósíthatjuk az operátort. Megvalósíthatjuk globális függvénnyel is. Amelyik jobban tatszik.
| tagfüggvénnyel |
class vec2D{
double x, y;
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
double getX()const{ return x; }
double getY()const{ return y; }
vec2D operator*(double d)const{ return vec2D(x*d, y*d); }
}; |
| globális függvénnyel |
class vec2D{
double x, y;
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
double getX()const{ return x; }
double getY()const{ return y; }
};
vec2D operator*(const vec2D &v, double d){
return vec2D(v.getX()*d, v.getY()*d);
} |
| globális függvénnyel, ha nincs getter: friend |
class vec2D{
double x, y;
friend vec2D operator*(const vec2D &, double);
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
};
vec2D operator*(const vec2D &v, double d){
return vec2D(v.x*d, v.y*d);
} |
Friend-ként deklaráljuk, így hozzáfér a privát dolgokhoz. Mindegy, hogy a friend deklaráció az osztály private vagy public részében van, nincs semmi hatással a friend-re. Lehet leg ne haszáljunk friend-et, a getteres megoldás sokkal jobb.
| friend függvény definíciója az osztályban |
class vec2D{
double x, y;
friend vec2D operator*(const vec2D &v, double d){
return vec2D(v.x*d, v.y*d);
}
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
}; |
Lehetséges, hogy a friend függvényt teljes egészében az osztálydekalrációban írjuk meg. Ett l ez nem lesz tagfüggvény, továbbra is globális függvény marad. Más szóval: ha egy függvény el tt szerepel a friend kulcsszó, akkor az a függvény globális függvény.
b)
double * Vec2D: csak globális függvénnyel valósítható meg.
class vec2D{
double x, y;
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
double getX()const{ return x; }
double getY()const{ return y; }
};
vec2D operator*(double d, const vec2D &v){
return vec2D(v.getX()*d, v.getY()*d);
} |
Ha van Vec2D*double függvényünk, azt is felhasználhatjuk:
| A Vec2D*double felhasználásával |
class vec2D{
double x, y;
public:
vec2D(double x = 0, double y = 0) :x(x), y(y){}
double getX()const{ return x; }
double getY()const{ return y; }
vec2D operator*(double d)const{ return vec2D(x*d, y*d); }
};
vec2D operator*(double d, const vec2D &v){
return v*d;
} |
Természetesen a double*Vec2D is megvalósítható friend-del. Ha akarod, próbáld ki. (Freind használata továbbra sem javasolt. Miért? Mert ha módosítunk az osztály bels felépítésén, ezekhez a függvényekhez is hozzá kell nyúlni. Ha macerásabb vagy lehetetlen lenne friend nélkül megvalósítani, akkor természetesen haználhatjuk, ZH-ban is megengedett.)
Készíts float értékeket tároló Verem osztályt! A verem egy olyan adattároló, amelybe a push függvénnyel tudunk új értéket betenni, a pop függvénnyel pedig kivenni. Mindig az utoljára betett értéket tudjuk kivenni, azaz az egymást követ pop hÍvások fordított sorrendben adják az értékeket, mint ahogy a push-sal betettük.
Legyen:
- alapértelmezett konstruktor
- destruktor
- másoló konstruktor
- = operátor
- push függvény:
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
class Verem {
float *t;
int n;
public:
Verem() :t{ nullptr }, n{ 0 } {}
~Verem() { delete[]t; }
Verem(const Verem & v) :t{ nullptr } {
*this = v;
}
Verem & operator=(const Verem & v) {
if (this == &v)
return *this;
delete[]t;
n = v.n;
t = new float[n];
for (int i = 0; i < n; i++)
t[i] = v.t[i];
return *this;
}
void push(float uj) {
float *temp = new float[n + 1];
for (int i = 0; i < n; i++)
temp[i] = t[i];
temp[n] = uj;
n++;
delete[]t;
t = temp;
}
float pop() {
if (n == 0)
throw std::domain_error("Ures verembol probaltal kivenni");
float *temp = new float[n - 1];
for (int i = 0; i < n - 1; i++)
temp[i] = t[i];
n--;
float ki = t[n];
delete[]t;
t = temp;
return ki;
}
};
int main() {
try {
Verem v;
v.push(2);
v.push(9);
v.push(-3.1f);
// Verem w{ v };
Verem w = v, z;
v.push(3.14f);
v = v;
z = (w = v);
for (int i = 0; i < 3; i++)
printf("%g\n", v.pop());
}
catch (const std::domain_error & h) {
printf("%s\n", h.what());
}
return 0;
} |
Készíts dinamikusan nyúló tömb, azaz vektor osztályt valós számok tárolására! Ahol szükséges, végezz hibakezelést! A hatékonyabb m ködés érdekében kiegészítheted további függvényekkel. Készítend :
- alapértelmezett konstruktor
- destruktor
- másoló konstruktor
- = operátor
- [] operátor 2 változatban: konstans és nem konstans
- push_back függvény: a paraméterként átvett értéket a tömb végéhez f zi (megnöveli a tömb méretét, és az új helyre beteszi az új elemet)
- globális print(vektor) függvény
- globális first(v,n) függvény: a v vektor els n elemét teszi az új vektorba, ezt adja vissza.
Próbáld meg önállóan is lekódolni, és azt küldd be óai munkaként.
Készíts sztring osztályt! Legyen
- alapértelmezett konstruktor
- destruktor
- másoló konstruktor (hívja meg az = operátort)
- = operátor
- [] operátor 2 változatban: konstans és nem konstans
- összef zés + operátorral
- karakter és C sztring és sztring objektum hozzáf zés += operátorral
- globális print(sztring) függvény
| 2. feladat: vektor osztály |
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
class vektor{
double *t;
int n;
public:
vektor() :t(NULL), n(0){}
~vektor(){ delete[]t; }
vektor(const vektor &masik);
vektor &operator=(const vektor &masik);
double &operator[](int i){
if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
return t[i];
}
const double &operator[](int i)const{
if (i < 0 || i >= n)throw std::out_of_range("vektor::operator[]: out of tange");
return t[i];
}
void push_back(double);
int getSize()const{ return n; }
void resize(int ujmeret);
};
vektor::vektor(const vektor &masik) :n(masik.n){
t = new double[n];
for (int i = 0; i < n; i++)
t[i] = masik.t[i];
}
const vektor &vektor::operator=(const vektor & masik){
if (this == &masik)
return *this;
delete[]t;
n = masik.n;
t = new double[n];
for (int i = 0; i < n; i++)
t[i] = masik.t[i];
return *this;
}
void vektor::push_back(double uj){
double *p = new double[n + 1];
for (int i = 0; i < n; i++)
p[i] = t[i];
p[n] = uj;
n++;
delete[]t;
t = p;
}
void print(const vektor &v){
printf("(");
for (int i = 0; i < v.getSize()-1; i++)
printf("%g, ", v[i]);
if (v.getSize()>0)printf("%g", v[v.getSize() - 1]);
printf(")\n");
}
vektor first(const vektor &v, int n){
vektor uj;
for (int i = 0; i < n; i++)
uj.push_back(v[i]);
return uj;
}
/*
// Hat konyabb v ltozat a first f ggv nyre
void vektor::resize(int ujmeret){
if (ujmeret < 0)throw std::domain_error("vektor::operator[]: ujmeret < 0");
double *p=new double[ujmeret];
const int eddig = ujmeret < n ? ujmeret : n;
for (int i = 0; i < eddig; i++)
p[i] = t[i];
n = ujmeret;
delete[]t;
t = p;
}
vektor first(const vektor &v, int n){
vektor uj;
uj.resize(n);
for (int i = 0; i < n; i++)
uj[i] = v[i];
return uj;
}
*/
int main(){
vektor v, v2;
for (int i = 0; i < 10; i++)
v.push_back(i+1);
print(v);
v2 = v;
print(v2);
v = first(v, 5);
print(v);
return 0;
} |