Pergunta

Alguém pode explicar por que seguinte código não irá compilar? Pelo menos no g ++ 4.2.4.

E mais interessante, porque ele irá compilar quando eu Membro do elenco para int?

#include <vector>

class Foo {  
public:  
    static const int MEMBER = 1;  
};

int main(){  
    vector<int> v;  
    v.push_back( Foo::MEMBER );       // undefined reference to `Foo::MEMBER'
    v.push_back( (int) Foo::MEMBER ); // OK  
    return 0;
}
Foi útil?

Solução

Você precisa realmente definir a algum lugar membro estático (após a definição de classe). Tente isto:

class Foo { /* ... */ };

const int Foo::MEMBER;

int main() { /* ... */ }

Isso deve se livrar da referência indefinida.

Outras dicas

O problema surge por causa de um confronto interessante de novos recursos C ++ e que você está tentando fazer. Primeiro, vamos dar uma olhada na assinatura push_back:

void push_back(const T&)

Ele está esperando uma referência a um objeto do tipo T. Sob o antigo sistema de inicialização, existe um tal membro. Por exemplo, o seguinte código compila muito bem:

#include <vector>

class Foo {
public:
    static const int MEMBER;
};

const int Foo::MEMBER = 1; 

int main(){
    std::vector<int> v;
    v.push_back( Foo::MEMBER );       // undefined reference to `Foo::MEMBER'
    v.push_back( (int) Foo::MEMBER ); // OK  
    return 0;
}

Isso ocorre porque há um algum lugar objeto real que tem esse valor armazenado nele. Se, no entanto, pode mudar para o novo método de especificar membros const estáticas, como você tem acima, Foo::MEMBER não é mais um objeto. É uma constante, um pouco parecido com:

#define MEMBER 1

Mas, sem as dores de cabeça de uma macro pré-processador (e com segurança de tipo). Isso significa que o vetor, o que está esperando uma referência, não podem obter um.

O padrão C ++ exige uma definição para o seu membro const estático se a definição é de alguma forma necessária.

A definição é necessária, por exemplo, se o endereço é utilizado. push_back leva o seu parâmetro por referência const, e tão estritamente o compilador precisa do endereço de seu membro e você precisa defini-lo no espaço de nomes.

Quando você converter explicitamente a constante, você está criando um temporário e é este temporário, que está vinculado ao de referência (sob regras especiais no padrão).

Este é um caso muito interessante, e eu realmente acho que vale a pena levantar uma questão de modo que o DST ser alterado para ter o mesmo comportamento para o seu membro constante!

Embora, em um tipo estranho de maneira isso poderia ser visto como um uso legítimo do operador unário '+'. Basicamente o resultado da unary + é um rvalue e assim as regras para a ligação do rvalues ??para referências const aplicar e nós não usamos o endereço do nosso membro const estática:

v.push_back( +Foo::MEMBER );

Aaa.h

class Aaa {

protected:

    static Aaa *defaultAaa;

};

Aaa.cpp

// You must define an actual variable in your program for the static members of the classes

static Aaa *Aaa::defaultAaa;

Não faço ideia por que as obras do elenco, mas Foo :: MEMBRO não é alocado até a primeira vez Foo é carregado, e uma vez que você nunca carregá-lo, nunca é alocado. Se você tivesse uma referência a um lugar Foo, ele provavelmente iria funcionar.

Quanto à segunda pergunta: push_ref leva de referência como um parâmetro, e você não pode ter uma referência para memeber const estático de uma classe / struct. Uma vez que você chamar static_cast, uma variável temporário é criado. E uma referência para este objeto pode ser passado, tudo funciona muito bem.

Ou, pelo menos, o meu colega que resolveu este disse isso.

Com C ++ 11, o acima seria possível para tipos básicos como

class Foo {
public:  
  static constexpr int MEMBER = 1;  
};

A parte constexpr cria uma estática expressão em oposição a um estático variável - e que se comporta exatamente como uma definição de método em linha extremamente simples. A abordagem mostrou um pouco vacilante com constexprs C-corda dentro de classes de modelo, no entanto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top