Если вы хотите, чтобы ваши классы запускались в определенном порядке, я думаю, что язык сценариев слишком сложен. Вам нужен топографический вид.
Что вам нужно
Повышение имеет топографический вид . Вы также можете ознакомиться с очень читаемой реализацией C #, с которой вам будет легко перейти на C ++, если библиотека boost для вас немного сложна. Это можно найти здесь .
Что он делает
По сути, вы предоставляете алгоритм сортировки своим классам, а затем добавляете их зависимости (алгоритм сортировки рассматривает их как вершины и ребра). Как только вы закончите, вы применяете алгоритм. Вы получаете то, что объекты зависят от чего.
Я использовал этот точный метод, когда у меня было несколько подсистем, которые нужно было загрузить, некоторые из которых полагались на другие, некоторые - нет. Количество подсистем было произвольным и из-за природы плагина, неизвестного во время компиляции.
Я назначил каждой подсистеме уникальный идентификатор (кстати, используя boost::uuid
), и каждая подсистема перечислила идентификаторы других подсистем, которые полагались на нее. Это было передано сортировщику, и мой заказ инициализации вышел из задней части.
Чтобы помочь вам на вашем пути, вот некоторый код (ПРИМЕЧАНИЕ: на данный момент я не знал, что существует библиотека boost, это моя собственная реализация, основанная на коде C # по ссылке, которую я предоставил выше.) *
// class TopologicalSorter
template<typename TYPE> class TopologicalSorter
{
private:
std::vector<TYPE> m_Vertices;
std::vector<std::vector<TYPE> > m_Matrix;
std::vector<TYPE> m_Sorted;
TYPE m_nNumVerts;
TYPE m_nSize;
// private helpers
int noSuccessors()
{
bool isEdge;
for(TYPE row(0); row < m_nNumVerts; row++)
{
isEdge = false;
for(TYPE col(0); col < m_nNumVerts; col++)
{
if(m_Matrix[row][col] > 0) // edge to another?
{
isEdge = true;
break;
};
};
if(!isEdge)
return(row);
};
return(-1); // nope!
}; // eo noSuccessors
void deleteVertex(TYPE _vertex)
{
if(_vertex != m_nNumVerts - 1)
{
for(TYPE j(_vertex); j < m_nNumVerts - 1; j++)
m_Vertices[j] = m_Vertices[j + 1];
for(TYPE row(_vertex); row < m_nNumVerts - 1; row++)
moveRowUp(row, m_nNumVerts);
for(TYPE col(_vertex); col < m_nNumVerts - 1; col++)
moveColLeft(col, m_nNumVerts - 1);
};
--m_nNumVerts;
}; // eo deleteVertex
void moveRowUp(TYPE _row, TYPE _length)
{
for(TYPE col(0); col < _length; col++)
m_Matrix[_row][col] = m_Matrix[_row + 1][col];
}; // eo moveRowUp
void moveColLeft(TYPE _col, TYPE _length)
{
for(TYPE row(0); row < _length; row++)
m_Matrix[row][ _col] = m_Matrix[row][_col + 1];
}; // eo moveColLeft
public:
TopologicalSorter(TYPE _size) : m_nNumVerts(0)
, m_Vertices(_size)
, m_Matrix(_size)
, m_Sorted(_size)
, m_nSize(_size)
{
assert(_size > 0);
for(TYPE i(0); i < m_nSize; ++i)
{
for(TYPE j(0); j < m_nSize; ++j)
m_Matrix[i].push_back(0);
};
}; // eo ctor
~TopologicalSorter(){};
// public methods
TYPE addVertex(TYPE _vertex)
{
m_Vertices[m_nNumVerts++] = _vertex;
return(m_nNumVerts - 1);
}; // eo addVertex
void addEdge(TYPE _start, TYPE _end)
{
m_Matrix[_start][_end] = 1;
}; // eo addEdge
std::vector<TYPE> sort()
{
int currVertex;
while(m_nNumVerts)
{
currVertex = noSuccessors();
coreAssert(currVertex != -1, "Graph has cycles");
m_Sorted[m_nNumVerts - 1] = m_Vertices[currVertex];
deleteVertex(currVertex);
}; // eo while(m_nNumVerts)
return(std::move(m_Sorted));
}; // eo sort
}; // eo class TopologicalSorter
Теперь, вот как это было использовано при загрузке и инициализации подсистем (Uuid это просто typedef
для boost::uuids::uuid
)
// create a topological sorter:
utility::TopologicalSorter<ManagerVector_sz> sorter(m_Managers.size());
std::map<Uuid, ManagerVector_sz> indexes;
// add vertices and edges
for(ManagerVector_sz i(0); i < m_Managers.size(); ++i)
indexes.insert(std::pair<Uuid, ManagerVector_sz>(m_Managers[i]->getUuid(), sorter.addVertex(i)));
for(ManagerVector_sz i(0); i < m_Managers.size(); ++i)
{
if(m_Managers[i]->getDependencies().size())
{
for(ManagerVector_sz j(0); j < m_Managers[i]->getDependencies().size(); ++j)
sorter.addEdge(i, indexes[m_Managers[i]->getDependencies()[j]]);
};
};
// get the order in which we should initialise
m_SortedIndexes = sorter.sort();
// and initialise
ManagerVector* mv(&m_Managers);
std::for_each(m_SortedIndexes.rbegin(),
m_SortedIndexes.rend(),
[&mv](int i){mv->at(i)->initialise();});
Надеюсь, это поможет и избежать ненужного сценария!