How does this do what it does (C++ classes, use of colon)

Here are 6 scenarios where using C-style arrays has unexpected behavior (or simply doesn't work at all):

#include <cstddef>
#include <iostream>
#include <array>
#include <type_traits>

#define USE_STD_ARRAY 0

#if USE_STD_ARRAY
using array3i = std::array<int, 3>;
#else
using array3i = int[3];
#endif

#if USE_STD_ARRAY // these portions are disabled because they don't compile when using C-style arrays

// 1.
// C-style arrays cannot be returned from functions
array3i functionReturningArray() {
    array3i a = {1, 2, 3};
    return a;
}

#endif

// 2.
// Can C-style arrays be passed by value?
void fun(array3i array) { 
    array[0] = 42;
}

void test2() {
    array3i a = {1, 2, 3};
    fun(a);
    std::cout << a[0] << std::endl; // wrong result
    // The array a is now {42, 2, 3}, because the function operates
    // on the actual array, not on a copy of it. C-style arrays 
    // can never be passed by value.
}

// 3.
// C-style arrays as function arguments look exactly the same
// as variables of array type, but they secretly are pointers:
int sum(array3i array) {
    int sum = 0;
    size_t size = sizeof(array) / sizeof(array[0]);
    // Wrong: sizeof(array) is the same as sizeof(int*)
    for (size_t i = 0; i < size; i++)
        sum += array[i];
    return sum;
}

void test3() {
    array3i a = {1, 2, 3};
    int res = sum(a);
    std::cout << res << std::endl; // wrong result
}

#if USE_STD_ARRAY

// 4.
// C-style arrays cannot be assigned or copied like normal variables.
void test4() {
    array3i a = {10, 20, 30};
    array3i b = a; // error
}

#endif

#if USE_STD_ARRAY

// 5.
// C-style array members of a class or struct cannot be initialized
// in the constructor:
struct S {
    array3i a;
    S(const array3i &a)
        : a(a) {} // error: array used as initializer
};

#endif

// 6. 
// C-style arrays implicitly decay to pointers to the first element,
// they don't follow the usual value semantics.
void test6() {
    array3i a = {1, 2, 3};
    auto b = a;
    if (std::is_same<decltype(b), int *>::value)
        std::puts("b is a pointer to int?!");
}

int main() {
    test2();
    test3();
    test6();
}

(Compile using g++ -std=c++11 file.cpp)

If you set #define USE_STD_ARRAY 1, everything works as expected.

What do you mean? Of course you can index a std::array:

#include <array>
#include <iostream>

int main() {
  std::array<int, 3> arr = {1, 2, 3};
  int third_element = arr[2];
  std::cout << third_element <<  std::endl; // 3
  arr[0] = 42;
  std::cout << arr[0] << std::endl; // 42
}

An array is a common concept, and I would argue that std::array matches the array/list/vector types in other languages more closely than C-style arrays with their quirks.

To be absolutely clear, std::array is a drop-in replacement for C-style arrays, but without the weird behavior demonstrated in the code I posted at the top of this reply.