Group of data elements (members) of potentially different types grouped together under one name
struct DataType {
member_type_01 member01;
member_type_02 member02;
member_type_03 member03;
...
} data_variable1, data_variable2;
struct DataType {
member_type_01 member01;
member_type_02 member02;
member_type_03 member03;
...
};
DataType data_variable1;
DataType data_variable2;
struct
specification
struct Car {
string brand;
string model;
int year;
};
struct
usage
struct
usage (pointers)
struct Rational { int num, den; };
Rational create(int n, int d);
Rational simplify(const Rational& r);
Rational add(const Rational& r1, const Rational& r2);
Abstract type | Class |
---|---|
Type and variable
|
Class and object
|
Functions
|
Methods (messages)
|
Function parameters
|
Method parameters
|
Are we just doing the same thing and just changing the syntax?
(for now)
A class consists on attributes and methods (or member functions)
class Class {
typeA1 attribute1;
typeA2 attribute2;
...
typeM1 method(parameters) {
implementation;
}
};
class Class {
typeA1 attribute1;
typeA2 attribute2;
};
Abstract type | Class |
---|---|
|
|
this
can be omitted if there are no ambiguities.
|
|
private:
Cannot access except from within the classpublic:
Can access from everywhereUsually: private attributes and public methods
class String {
private:
int size;
char text[256];
public:
void fill(int count, char c) {
size = count;
for (int i = 0; i < count; ++i)
text[i] = c;
}
};
Methods that define operations executed when creating an object
Constructors: for setting up default attribute values.
class Complex {
private:
float _real, _imag;
public:
Complex() {
_real = _imag = 0;
}
};
Complex c;
// c._real = 0; c._image = 0;
Complex* pc = new Complex;
// pc->_real = 0; pc->_imag = 0;
Constructors: for setting up parametrized attribute values regardless of visibility.
class Complex {
private:
float _real, _imag;
public:
Complex(float real, float imag) {
_real = real; _imag = imag;
}
};
// Complex c; Complex* pc = new Complex <-- Can't do these
Complex c(1,0);
//c._real=1; c._imag=0;
Complex* pc = new Complex(1,0);
// pc->_real = 1; pc->_imag = 0;
What happens when using classes as attributes?
class ElectromagneticWave {
private:
Complex phasor_vertical, phasor_horizontal;
public:
ElectromagneticWave() {
phasor_vertical = Complex(0,-1);
phasor_horizontal = Complex(1,0);
}
}
Does not compile if Complex()
does not exist (needs to construct attributes)
What happens when using classes as attributes?
class ElectromagneticWave {
private:
Complex phasor_vertical, phasor_horizontal;
public:
ElectromagneticWave() :
phasor_vertical(0,-1), phasor_horizontal(1,0) {}
It actually invokes the constructores.
Constructors: more versatile with default parameter values.
class Complex {
private:
float _real, _imag;
public:
Complex(float real = 0, float imag = 0) {
_real = real; _imag = imag;
}
};
Complex c1; // c1._real=0; c._imag=0;
Complex c2(1,1); // c2._real=1; c2._imag=1;
Complex c3(-1); // c3._real=-1; c3._imag=0;
Complex c4 = 2; // c4._real=2; c4._imag=0;
Constructors: can be used to reserve resources (such as memory)
class VectorInt {
private:
int* data;
int size;
public:
VectorInt(int s) {
size = s; data = new int[s];
}
};
{
VectorInt vi(128);
...
}
What about freeing that memory?
Methods that define operations executed when object dissappears from memory
Destructors
class VectorInt {
private:
int* data;
int size;
public:
VectorInt(int s) {
size = s; data = new int[s];
}
};
Destructors
class VectorInt {
private:
int* data;
int size;
public:
VectorInt(int s) {
size = s; data = new int[s];
}
~VectorInt() {
delete[] data;
}
};
{
VectorInt vi(128);
...
} // vi dissappears here
The data is now deleted seamlessly
Methods with special names are interpreted as operators.
Operators: can be defined as methods with special names
class Complex {
private:
float _real, _imag;
public:
Complex(float real = 0, float imag = 0) {
_real = real; _imag = imag;
}
Complex operator+(const Complex& that) const {
return Complex(this->_real+that._real,this->_image+that._image);
}
};
Operators: some of them can only be functions
Operators: some of them can only be methods
class VectorInt {
private:
int* data;
int size;
public:
VectorInt(int s) {
size = s; data = new int[s];
}
~VectorInt() {
delete[] data;
}
int& operator[](int i) { return data[i]; }
int operator[](int i) const { return data[i]; }
};
It is still a good idea to separate specification from implementation