Primeiro, tomaremos um resumo UDT (tipo definido pelo usuário) padrão:
struct foo { virtual void f() = 0; }; // normal abstract type
foo obj;
// error: cannot declare variable 'obj' to be of abstract type 'foo'
Lembremos também que podemos instanciar a UDT ao mesmo tempo que a definimos:
struct foo { foo() { cout << "!"; } }; // just a definition
struct foo { foo() { cout << "!"; } } instance; // so much more
// Output: "!"
Vamos combinar os exemplos e lembrar que podemos definir uma UDT sem nome :
struct { virtual void f() = 0; } instance; // unnamed abstract type
// error: cannot declare variable 'instance' to be of abstract type '<anonymous struct>'
Não precisamos mais da prova sobre a UDT anônima, para que possamos perder a função virtual pura. Também renomeando instance
para foo
, ficamos com:
struct {} foo;
Chegando perto.
Agora, e se essa UDT anônima derivasse de alguma base?
struct bar {}; // base UDT
struct : bar {} foo; // anonymous derived UDT, and instance thereof
Finalmente, o C ++ 11 introduz inicializadores estendidos , para que possamos fazer coisas confusas como esta:
int x{0};
E isto:
int x{};
E, finalmente, isso:
struct : bar {} foo {};
Esta é uma estrutura sem nome derivada de bar, instanciada como foo com um inicializador em branco.