Мы постоянно, что-то программируем. Например, доступ к элементам массива. При этому очень часто решения, которые мы с Вами реализуем являются частными. То есть для частного случая. Надо что то исправить начинаем писать снова. Плохо это. С++ позволяет нам делать универсальные решения. Вот как это реализуется мы с Вами и посмотрим. Идея вот в чем. мы хотим в программе использовать массив. Что мы делаем? Берем класс допустим CStringArray и начинаем. Но самое интересное что если вдруг не дай бог придется изменить базовый класс то надо исправлять кучу кода. Выход из данной ситуации в использовании механизмов виртуальных функций и наследовании. Давайте посмотрим схему.

У нас есть основной самый первый класс CBaseAbstract, в нем просто описаны функции, которые нам необходимы без их реализации. Вот такая пустышка.
class CBaseAbstract
{
public:
CBaseAbstract();
virtual ~CBaseAbstract();
virtual void Add(CString s);
virtual void Remove(int iIndex);
virtual CString GetAt(int iIndex);
virtual int GetCount();
};
CBaseAbstract::CBaseAbstract()
{}
CBaseAbstract::~CBaseAbstract()
{}
void CBaseAbstract::Add(CString s)
{}
void CBaseAbstract::Remove(int iIndex)
{}
CString CBaseAbstract::GetAt(int iIndex)
{return "";}
int CBaseAbstract::GetCount()
{return 0;}
И есть класс, который умеет вызывать функции этой пустышки или класса наследника.
class CWork
{
public:
CWork(CBaseAbstract *pointer);
~CWork();
void Add(CString s);
void Remove(int iIndex);
CString GetAt(int iIndex);
int GetCount();
private:
CBaseAbstract* cPointer;
};
CWork::CWork(CBaseAbstract *pointer)
{
cPointer=pointer;
}
CWork::~CWork()
{}
void CWork::Add(CString s)
{
cPointer->Add(s);
}
void CWork::Remove(int iIndex)
{
cPointer->Remove(iIndex);
}
CString CWork::GetAt(int iIndex)
{
return cPointer->GetAt(iIndex);
}
int CWork::GetCount()
{
return cPointer->GetCount();
}
Ну, и теперь мы спокойно можем реализовывать любой класс как наследник от CBaseAbstract, перегружать его виртуальные функции, но работать в программе мы все равно будем с CWork. При том совершенно одинаково в не зависимости от того на какой физической базе класс.
#include "stdafx.h"
#include "MFCArray.h"
#include "StlArray.h"
#include "work.h"
#include "iostream.h"
void main()
{
CMFCArray mfcArray;
CStlArray stlArray;
CWork cw1(&mfcArray);
CWork cw2(&stlArray);
cw1.Add("Hello"); cw2.Add("Hello");
cw1.Add("Abstract"); cw2.Add("Abstract");
cout << cw1.GetCount() << " " << cw2.GetCount() << endl;
cout << cw1.GetAt(1) << " " << cw2.GetAt(1) << endl;
}
Естественно, что классы CStlArray и CMFCArray я породил от CBaseAbstract, но внутренняя реализация каждого класса своя.
#include "BaseAbstract.h"
#include "afxcoll.h"
class CMFCArray : public CBaseAbstract
{
public:
CString GetAt(int iIndex);
int GetCount();
void Add(CString s);
CMFCArray();
virtual ~CMFCArray();
private:
CStringArray ca;
};
#include "BaseAbstract.h"
#include "iostream.h"
#include "vector"
#include "afxwin.h"
using namespace std ;
typedef vector<CString> STLStringArray;
class CStlArray : public CBaseAbstract
{
public:
CString GetAt(int iIndex);
int GetCount();
void Add(CString s);
CStlArray();
virtual ~CStlArray();
private:
STLStringArray ca;
};
Реализация методов совершенно тривиальная и Вы можете посмотреть ее в проекте. Использование данной технологии дает вам широкие возможности к повторному использованию кода. Например для баз данных создали свои классы CBaseAbstract и CBaseWork и работайте хоть с DAO хоть с ADO или еще с чем. С какой то черты, а точнее с класса в данном случае CBaseWork код Ваш меняться не будет при заменен метода доступа к данным. А значит и элементы управления универсальные и так далее. Вся работа будет сосредоточена на производном классе от CBaseAbstract.