Как эта конкретная структура функционирует так? (arcsynthesis современное 3D графическое программирование)

Я использую учебное пособие по Arcsynthesis для изучения современного программирования трехмерной графики, и, хотя я понимаю большую его часть, я столкнулся с проблемой, которую автор называет «сложный код управления», я не могу понять, как работает этот код:

struct Instance
{
typedef glm::vec3(*OffsetFunc)(float);

OffsetFunc CalcOffset;

glm::mat4 ConstructMatrix(float fElapsedTime)
{
glm::mat4 theMat(1.0f);

theMat[3] = glm::vec4(CalcOffset(fElapsedTime), 1.0f);

return theMat;
}
};Instance g_instanceList[] =
{
{StationaryOffset},
{OvalOffset},
{BottomCircleOffset},
};

Я не совсем понимаю, как указатель функции устанавливается внутри структуры в g_instanceList []. Я не понимаю синтаксически, как это работает, а затем, как этот g_instanceList используется в следующем сегменте:

float fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
for(int iLoop = 0; iLoop < ARRAY_COUNT(g_instanceList); iLoop++)
{
Instance &currInst = g_instanceList[iLoop];
const glm::mat4 &transformMatrix =
currInst.ConstructMatrix(fElapsedTime);

glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE,     glm::value_ptr(transformMatrix));
glDrawElements(GL_TRIANGLES, ARRAY_COUNT(indexData), GL_UNSIGNED_SHORT, 0);
}

Я думал, что был довольно знаком с c ++ к этому моменту, но этот синтаксический сахар является новым для меня.
Заранее спасибо 🙂

2

Решение

Я не совсем понимаю, как указатель на функцию устанавливается внутри структуры в g_instanceList []

Instance является тип агрегата. Он может иметь функцию-член, но это не делает его не агрегатом. В C ++ 98/03 объекты агрегатных типов могут быть инициализированы с агрегатной инициализацией:

struct Aggregate
{
int x;
int y;
};

Aggregate agg = { 5, 4 };
assert(4 == agg.y); //Will be true.

Каждый член в структуре инициализируется с каждым отдельным значением в порядке, в котором эти члены объявлены в структуре. 5 входит в x и 4 входит в y,

Instance это совокупность. И в нем ровно один член. Этот член является типом указателя на функцию, но C ++ это не волнует; это значение, и его можно использовать для инициализации агрегата.

Массив C ++ также является агрегатом. Таким образом, вы можете инициализировать массив с агрегатной инициализацией:

int arr[4] = {3, 45, 9, 81};

C ++ также позволяет вам инициализировать массив с агрегатной инициализацией, где размер массива определяется инициализатором:

int arr[] = {5, 2};
//arr will have 2 elements.

Следовательно, g_instanceList является массивом и, следовательно, агрегатом, который подлежит агрегатной инициализации. Он имеет размер, который будет определяться числом значений, предоставленных синтаксисом агрегатной инициализации. Каждый элемент массива также агрегат, поэтому каждый элемент массива может быть агрегатно инициализирован.

Instance g_instanceList[] =
{
{StationaryOffset},
{OvalOffset},
{BottomCircleOffset},
};

Каждый член совокупного списка инициализации сам по себе является совокупной инициализацией, которая инициализирует Instance объект. StationaryOffset а остальные являются указателями на функции, которые совпадают с подписью члена Instance, Так вот как Instance::CalcOffset заполняется.


как этот g_instanceList используется в следующем сегменте здесь

Как это используется — довольно распространенный C ++. Первая строка получает ссылку на один из Instance элементы массива. Это сделано только для того, чтобы сделать код короче; это не должно использовать g_instanceList[iLoop] каждый раз говорить о Instance он использует. Вторая строка вызывает функцию-член Instance (который сам вызывает внутренний указатель на функцию), сохраняя результат в переменной.

Если вы говорите о ARRAY_COUNT, это просто удобный макрос для получения … ну, количество элементов массива. Компилятор C ++ знает, насколько велик g_instanceList есть, поэтому макрос используется, чтобы компилятор вычислял его сам. Таким образом, если g_instanceList Изменения длины массива, вам не нужно проходить всю кодовую базу, чтобы найти каждое использование длины массива. Кроме того, вы никогда не должны прямо указывать длину; вы можете сделать вывод об этом через агрегатную инициализацию.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]