[C++] Como acesso variaveis/metodos static?

Boa tarde a todos,

eu já tenho uma boa experiência em Java e tomei a decisão de aprendar C++ apenas para obter mais conhecimento (sem contar que eu sempre quis aprender essa linguagem). Como eu já conheço o básico da linguagem como estruturas de repetição, variáveis, etc… decidi começar pelo POO.

Eu optei pelo meu primeiro exemplo que eu fiz em Java, um banco, que possui contas, clientes, etc…

Eis a classe conta:

Conta.cpp

#include <string>
#include <iostream>
#include <cstdlib>
#include <time.h>

using namespace std;

class Conta {
    private:

        static const int QUANTIDADE_CONTA = 20;
        static int contasCriadas;
        unsigned int numeroConta;
        double saldo;
        string dono;

    public:

        static int contas[QUANTIDADE_CONTA];     //isso aqui é temporário, irei coloca-la na classe banco assim que eu cria-la
        Conta(double saldoInicial, string donoInicial) {
            srand(time(NULL));
            saldo = saldoInicial;
            dono = donoInicial;
            numeroConta = rand();
            contas[contasCriadas++] = numeroConta; //aqui da o erro
        }

        int getNumeroConta() {return numeroConta;}
        void setNumeroConta(int novoNumeroConta) {numeroConta = novoNumeroConta;}

        double getSaldo() {return saldo;}
        void sacar(double valor) {saldo -= valor;}
        void depositar(double valor) {saldo += valor;}

        string getDono() {return dono;}
        void setDono(string novoDono) {dono = novoDono;}
};

Quando eu tento compilar ele da o seguinte erro:

Eu pesquisei no Google e achei http://stackoverflow.com/questions/272900/c-undefined-reference-to-static-class-member

Mas não se aplica ao meu caso.

Informações adicionais: Estou usando Code::Blocks como IDE e o GNU GCC Compiler como compilador.

Vou dar um exemplo bem pequeninho, que também lhe fala porque é que usar membros static em C++ é um porre. Acho que é de propósito.

/* teste.hpp */
class Teste {
private:
    static int x;
public: 
    int z;
    void teste();
};
/* teste.cpp */
#include "teste.hpp"
// A definição a seguir é obrigatória que exista em no máximo um dos fontes que usam "teste.hpp", tipicamente deve ser feita
// em "teste.cpp" que contém a implementação da classe Teste.
int Teste::x; 
// Mais definições da classe "Teste"...
void Teste::teste() {
}

Eu costumo declarar assim:

/*static*/ int Teste::x;

para me lembrar que esse membro x foi declarado como static na classe Teste. Você não pode tirar o comentário dessa palavra, senão dá erro de compilação.

[quote=entanglement]Vou dar um exemplo bem pequeninho, que também lhe fala porque é que usar membros static em C++ é um porre. Acho que é de propósito.

/* teste.hpp */
class Teste {
private:
    static int x;
public: 
    int z;
    void teste();
};
/* teste.cpp */
#include "teste.hpp"
// A definição a seguir é obrigatória que exista em no máximo um dos fontes que usam "teste.hpp", tipicamente deve ser feita
// em "teste.cpp" que contém a implementação da classe Teste.
int Teste::x; 
// Mais definições da classe "Teste"...
void Teste::teste() {
}

Eu costumo declarar assim:

/*static*/ int Teste::x;

para me lembrar que esse membro x foi declarado como static na classe Teste. Você não pode tirar o comentário dessa palavra, senão dá erro de compilação.
[/quote]

Boa noite, obrigado por responder.

Eu raramente (leia-se muito raramente) uso static em Java, as chances de eu ter que usar em C++ deve ser muito menor. Apenas para saber como funciona (e no caso de alguém perguntar eu saberei responder :stuck_out_tongue: ). Eu também não gosto muito da idéia de usar static a não ser que seja a única forma de resolver o meu problema.

No caso, aonde eu colocaria o

int Conta::contas; //como se trata de um array, eu preciso declara-lo de maneira diferente?Como por exemplo colocar []

para que eu possa usar contas[] dentro do construtor?

Eu criei 2 arquivos: Conta.cpp e Conta.h . Não vi nenhum conta.hpp.

Ah, eu chamei o arquivo de .hpp mas pode ser .h também.
É que prefiro, em meus projetos, chamar um arquivo de includes de .hpp em vez de .h para lembrar que ele contém código C++, não C puro.
No seu caso, a definição do membro (ele fica “solto” assim mesmo) deve ficar no arquivo .cpp.

Note que “declaração” e “definição” em C++ são conceitos distintos, e normalmente a declaração fica em um arquivo .h ou .hpp, e a definiçao em um arquivo .cpp (é claro que estou simplificando, é só para generalizar).

Em Java a “declaração” e a “definição” são a mesma coisa, e é isso que confunde um pouco as coisas.

[quote=entanglement]Ah, eu chamei o arquivo de .hpp mas pode ser .h também.
É que prefiro, em meus projetos, chamar um arquivo de includes de .hpp em vez de .h para lembrar que ele contém código C++, não C puro.
No seu caso, a definição do membro (ele fica “solto” assim mesmo) deve ficar no arquivo .cpp.

Note que “declaração” e “definição” em C++ são conceitos distintos, e normalmente a declaração fica em um arquivo .h ou .hpp, e a definiçao em um arquivo .cpp (é claro que estou simplificando, é só para generalizar).

Em Java a “declaração” e a “definição” são a mesma coisa, e é isso que confunde um pouco as coisas.
[/quote]

Nem tinha pensado no .h :oops:

No arquivo .h eu declaro apenas os metodos ou também as variaveis de classe e de instancia?

Em muitos casos, métodos static podem ser transformados em funções não associadas a classe nenhuma.

[quote=Sem_Nome][quote=entanglement]Ah, eu chamei o arquivo de .hpp mas pode ser .h também.
É que prefiro, em meus projetos, chamar um arquivo de includes de .hpp em vez de .h para lembrar que ele contém código C++, não C puro.
No seu caso, a definição do membro (ele fica “solto” assim mesmo) deve ficar no arquivo .cpp.

Note que “declaração” e “definição” em C++ são conceitos distintos, e normalmente a declaração fica em um arquivo .h ou .hpp, e a definiçao em um arquivo .cpp (é claro que estou simplificando, é só para generalizar).

Em Java a “declaração” e a “definição” são a mesma coisa, e é isso que confunde um pouco as coisas.
[/quote]

Nem tinha pensado no .h :oops:

No arquivo .h eu declaro apenas os metodos ou também as variaveis de classe e de instancia?[/quote]

No arquivo .h você precisa declarar tudo que está na classe - métodos e variáveis de classe e de instância (usando a terminologia Java), tanto faz se forem privados (a visibilidade default), públicos ou protected ou friend.

Infelizmente, em C++ não existem “declarações incompletas” (ou seja, você declara apenas a interface pública de uma classe e eventuais variáveis privadas de instância ou de classe - vamos usar os nomes habituais em C++, membros privados e membros privados estáticos - ficassem declaradas apenas na implementação.) Tais variáveis privadas precisam ser declaradas também.

O único tipo de declaração incompleta que existe em C++ é uma que é usada para podermos ter classes recursivamente dependentes, e que consiste em apenas indicar que um determinado identificador é o nome de uma classe:

class X;

Quando uma classe Y precisa usar uma declaração incompleta dessa classe X antes que ela tenha sido declarada completamente, ela só se pode referenciar a X usando um ponteiro ou “smart pointer”.