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

Цели и принципи

Цели на обектно-ориентирания дизайн

Принципи на обектно-ориентирания дизайн


Наследяване и полиморфизъм

Наследяване в C++

Наследяването позволява проектирането на общи (базови) класове, които могат да бъдат специализирани за други (по-частни) класове, с повторно използване на кода на общия клас от специализираните (производни)  класове.
class Person {       // base class  
private:
string name; // name
string ssn; // social security number
public:
//...
void print(); // print data
string getName(); // retrieve name
};
class Student : public Person { // derived class
private:
string major; // major subject
int gradYear; // graduate year
public:
//...
void print(); // print data
void changeMajor(string newMajor); // change major
 };
Член-функции
Person person(...);       // define a person 
Student student(...); // define a student
cout << student.getName();// invokes Person::getName()
person.print(); // invokes Person::print();
student.print(); // invokes Student::print();
person.changeMajor("Math"); // ERROR!
student.changeMajor("Math"); // OK
void Person::print() // definition of Person print
{ cout << name << " " << ssn; }
void Student::print() // definition of Student print
{ Person::print(); // first print Person data
cout << major << gradYear;
}

Class Protection

class Base {
private:
int priv;
protected:
int prot;
public:
int publ;
};
class Derived: public Base {
void someMemberFunction()
{ cout << priv; // ERROR: private member
cout << prot; // OK
cout << publ; // OK
}
};
class Unrelated {
Base X;
void anotherMemberFunction()
{ cout << X.priv; // ERROR: private member
cout << X.prot; // ERROR: protected member
cout << X.publ; // OK
}
};

Конструктори и деструктори

Person::Person(const string &nm, const string &ss)  
: name(nm), ssn(ss) {} // initializer list
Student::Student(const string &nm, const string &ss,
const string &maj, int year)
: Person(nm, ss), // initialize Person data members
major(maj), // initialize member
gradYear(year) {} // initialize gradYear
Person::~Person() // Person destructor
{ ... }
Student::~Student() // Student destructor
{ ... }
Student* s = new Student(...);
//...
delete s; // calls ~Student() then ~Person()
    [person.cpp]

 Статично свързване
Person* pp[100];  
pp[0] = new Person(...);
pp[1] = new Student(...);

cout << pp[1]->getName(); // OK
pp[0]->print(); // calls Person::print()
pp[1]->print(); // calls Person::print()
pp[1]->changeMajor(...); // ERROR!

Динамично свързване и виртуални функции

class Person {       // base class  
virtual void print(); // print data
//...
};
class Student : public Person { // derived class
virtual void print(); // print data
//...
 };
Person* pp[100];
pp[0] = new Person(...);
pp[1] = new Student(...);

pp[0]->print(); // calls Person::print()
pp[1]->print(); // calls Student::print()
pp[1]->changeMajor(...); // OK
    [person.cpp]

Виртуални деструктори

Ако в даден клас се дефинират виртуални функции, тогава трябва да се дефинира и виртуален деструктор, дори да е празен.
delete [] pp;
When to use virtual destructors?
In C++, what’s a virtual destructor and when is it needed?

Полиморфизъм

Способността на променлива да приеме различни типове!


Шаблони (template)

Функции-шаблони

Класове-шаблони

template <typename Object>
class BasicVector {
Object* a; // array storing an element
int capacity; // length of array a
public:
BasicVector(int cap = 10) // constructor
{ capacity = cap;
a = new Object[capacity];// allocate array storage
}
Object& elemAtRank(int r) // access element at index r
{ return a[r]; }
// ...
};
BasicVector<int> iv(5);     // vector of 5 integers
BasicVector<double> dv(20); // vector of 20 doubles
BasicVector<string> sv(10); // vector of 10 strings
//...
iv.elemAtRank(3) = 8; // iv[3] = 8;
dv.elemAtRank(14) = 2.5; // dv[14] = 2.5
sv.elemAtRank(7) = "hello"; // sv[7] = "hello"


Изключения

Изключенията са неочаквани събития, които се случват по време на изпълнението на програмата.

Изключения-обекти

Използване на наследяване за дефиниране на нови типове за изключения

class MathException {  // generic math exception
private:
string errMsg; // error message
public:
MathException(const string& err) { errMsg = err; }
};
class ZeroDivisionException : public MathException {
public:
ZeroDivisionException(const string& err)
: MathException(err) {}
};
class NegativeRootException : public MathException {
public:
NegativeRootException(const string& err)
: MathException(err) {}
};

Изхвърляне (throwing) и прихващане (catching) на изключения

try {
// ...
if (divisor == 0) throw ZeroDivisionException("Division by zero");
//...
}
catch (ZeroDivisionException& zde)
{ // handle division by zero
}
catch (MathException& me)
{ // handle any math exception other than division by zero
}
След изпълнение на catch блока, изпълнението на програмата продължава с първия оператор след последния catch блок.

Спецификация на изключенията

void calculator() throw(ZeroDivisionException, NegativeRootException)
{
//...
}

void funct1(); // can throw any exception
void funct2() throw(); // can throw no exception

Общ клас за изключения

class RuntimeException {  // generic run-time exception
private:
string errorMsg;
public:
RuntimeException(const string& err) { errorMsg = err; }
string getMessage() const { return errorMsg; }
};
inline std::ostream& operator<<(std::ostream& out, const RuntimeException& e)
{ return out << e.getMessage(); }