Ir ao conteúdo

Posts recomendados

Postado

Começei a aprender sobre c++, umas das formas de se organizar os dados e as funcionalidades é usando header. Mas toda vez que tento compilar no metodo main ele não consegue enxergar um metodo que esta no header, todos os codigos aqui em baixo estão no mesmo projeto/pasta

 

#ifndef TESTEHEAD_H_INCLUDED
#define TESTEHEAD_H_INCLUDED

void andar();
void pegar();
void pular();

#endif // TESTEHEAD_H_INCLUDED
#include <iostream>

#include "testeHead.h"

using namespace std;

void andar(){
    cout << "andando..." << endl;
}

void pegar(){
    cout << "Pegando algo..." << endl;
}

void pular(){
    cout << "Pulando..." << endl;
}
#include <iostream>
#include "testeHead.h"

using namespace std;

int main ()
{
    pular();
    return 0;
}

Estou acompanhando algumas aulas, e esta igual ao que foi me mostrado

  • Amei 1
Postado

@vangodp Eu estava usando o codeblocks e acabei trocando de IDE e agora esta tudo normal, mas aproveitando esse post, porque nos precisamos de 2 codigos quando se trata de classe em c++ (header pra declaração e o outro em cpp pra implementação)? Não podemos simplesmente declarar e implementar tudo no header? Tem algo haver com herança, ou é como uma classe abstrata em outras linguagens? E como o compilador sabe onde esta as implementações dos metodos se no metodo main eu apenas inclui o header? Não há nada no header que conecta ao cpp da implementação

Postado
2 horas atrás, KXSY disse:

Utilize a linha de comando e o gcc que você vai aprender muito mais

@soumma essa trecho em uma resposta acima é perfeito para ilustrar o porque de sempre aparecerem esses questionamentos.

 

O I de IDE significa integrado. IDE significa ambiente integrado de desenvolvimento e é como viajar num ônibus sem janelas: quando chega você não sabe nada sobre o caminho :D 

 

Em seu programa, mesmo tendo umas poucas linhas, você usou

#include <iostream>

Em muitos casos você vai usar memory.h, math.h, SDL.h <stdlib.h> e outros desses headers. No entanto você não vai compilar essas funções todas que eventualmente estão em seu programa, coisas como cout, rand(), sort(), classes importantes como vetor<>, set<>, deque<> list<> e tantas outras que estão por exemplo em stdlib.h.

Se você escrever 300 classes para tratar um problema de seu interesse e escrever depois uns programas de teste para suas excelentes 300 funções, não vai querer compilar toda vez as 300 funções sabendo que você não mudou uma única linha delas.

 

Quando você compila um programa é gerado um código intermediário, muitas vezes chamado de programa objeto, que é  gravado com extensão .o ou .OBJ pelo compilador. Para gerar esse código o compilador lê o seu programa e precisa gerar código para todas as funções que estão nele. Para isso ele só precisa da declaração delas. Por isso você declara às vezes o que se chama de protótipo de uma função, algo como

int    pular( float );

Isso é o que basta para o compilador entender nas suas funções que ao encontrar 

int i = pular( 3.5 ); 

deve gerar código para chamar tal função com este nome e que retorna um int e tem um argumento float.

Basta isso. E se você logo abaixo escreveu

int n = pular ( "alto" );

O compilador vai saber que está em desacordo com a declaração que está no protótipo e vai gerar um erro de compilação.

Mas se o código correspondente a pular() não está em seus arquivos .cpp  não importa para o compilador porque o header tem toda a definição que importa.

 

Afinalpor exemplo  o código de cout também não está, nem o de sort() ou rand() ou sei lá.

O LINKER

Esse tipo de programa, como o LINK da Microsoft ou o ld no linux/UNIX , pega esses códigos intermediários gerados pelo seu compilador e outros obtidos com o sistema operacional por exemplo, ou comprados ou obtidos de alguém, e junta tudo para criar um arquivo executável. 

E para fazer isso ele usa informações do sistema sobre onde estão essas tais "bibliotecas" com essas mágicas funções. O Linker não compila nada. O compilador não gera nenhum programa. 

 

Link Dinâmico ou Estático

Esse é um outro pedaço da história: por exemplo, todos os programas de computador que escrevem uma mensagem na tela usam as mesmas funções do sistema, que criam uma janela na tela, coloca aqueles 3 botões de fechar, minimizar, maximizar e tal. Quando o LINKER gera o código para um programa algumas coisas podem ser deixadas para resolver quando o programa roda, e isso se chama link dinâmico. Você pode compilar seu programa em uma máquina que não tenha as funções de banco de dados por exemplo, mas qundo seu programa for rodar você vai levá-lo para um lugar que tenha isso.

Mas em outros casos você precisa incorporar direto no seu programa executável o código de certas funções. Porque? 

Simples: assim você garante que não vai chegar a rodar em uma máquina que não tenha esses códigos. Como é melhor? Depende. Lógico que se todo programa tiver que incorporar todo o código necessário não vai rolar. Por isso seu sistema Windows tem milhares de arquivos .DLL, sua máquina Linux tem milhares que arquivos .so. Por outro lado tem muitas razões para você querer incorporar funções direto em seu arquivo .EXE, como performance e um pouco de sossego.

 

O IDE

Mas quando você usa o IDE não vê nada disso. Claro, todo IDE tem comandos para só compilar seus programas rapidinho sem gerar executável ou tentar rodar um programa, mas em geral se começa co programas minúsculos que rodam direto na tela. Em geral o primeiro programa que o aluno escreve mostra uma mensagem fixa na tela, e para mudar a mensagem de Hello Wordl para qualquer outra é preciso compilar o programa de novo. Claro que não faz sentido na prática.  Você escreve um programa hoje e espera usá-lo muitas vezes. Mandar para alguém que não vai poder compilar, que só quer usar o programa. Nem todo computador do mundo tem o Code::Blocks ou ambiente de compilação de programas.

2 horas atrás, KXSY disse:
4 horas atrás, soumma disse:

Não podemos simplesmente declarar e implementar tudo no header?

Sim, isso é possível mas não é o padrão.

 

É possível desde que você tenha o código fonte de tudo. Veja o caso desses #include todos que a gente simplesmente declara sem qualquer noção de como foi escrito o código ou onde está. Ou seja, não é na prática possível. 

2 horas atrás, KXSY disse:

pode ajudar na parte de herança em C++ (mas eu não programo em C++ ainda então vou ficar devendo)

 

Não é assim. Nada tem a ver com herança, que é um conceito de derivação de classes, tipo uma especialização de classes e é comum à arquitetura de objetos e não uma característica dessa linguagem

4 horas atrás, soumma disse:

porque nos precisamos de 2 codigos quando se trata de classe em c++ (header pra declaração e o outro em cpp pra implementação)

 

Pois é: se leu até aqui já deve ter entendido que nada tem a ver com C++. Ou C. Ou java ou Pascal ou COBOL ou javascript. Funciona de modo idêntico. Em java por exemplo cada classe tem seu arquivo mas você tem aquelas pastas com centenas de arquivos .jar com classes prontas pra você usar...

 

Os header tem informação de declaração para o compilador e podem ser distribuídos para terceiros poderem usar seu código, suas classes, sem saber como ou de onde elas vieram.

Por outro lado você vai distribuir o código compilado e assim poderá usar suas rotinas em outro computador para gerar outros executáveis onde outros main() fazem outras coisas com suas rotinas.

 

imagine esse header coisas.h 

// coisas.h
#include "stdio.h"
#include "math.h"

void andar(float);
void pular(float);

// fim de coisas.h

e um programa C coisas.c --- tanto faz a linguagem

// coisas.c
#include "stdio.h"
#include "math.h"
void andar(float quanto)
{ 
    printf("Andando %f\n", quanto);
    return;
}

void pular(float quanto)
{ 
    printf("Pulando %f\n", quanto);
    return;
}
// fim de coisas.c

E você roda isso no terminal:

cc -c coisas.c

Vai gerar um arquivo coisas.o que você pode distribuir junto com o coisas.h, mas SEM o coisas.c. E quem tiver esses arquivos vai poder compilar programas que usam essas funções. Note que coisas.c não tem uma função main(). Não vai ser executado: só queremos gerar o objeto para distribuir pros clientes ou levar pra outros micros sem ter que compilar tudo de novo

#include  "coisas.h"

Com o coisas.h disponível, na outra máquina eu posso rodar cc -c pular.c que vai compilar um hipotético programa que usa essa rotina porque o header diz exatamente como compilar pular() e andar().

cc -c pular.c

E depois posso rodar

ld pular pular.o coisas.o 

e vai gerar o executável pular que pode ser levado para outro micro onde não tem nem o coisas.h nem o coisas.o e o cara digitar pular 1.2 e sair na tela

Pulando 1.2

É só um exemplo e as opções podem nem ser exatamente assim.

2 horas atrás, KXSY disse:

Isso vem de linguagens de programação mais antigas do que C, serve basicamente de interface (hearder) implementação (código .c) quando você tem uma interface

 

Se leu até aqui entendeu que não é o caso. A geração de código objeto (compilação) é separada da geração de programas executáveis (link)

 

2 horas atrás, KXSY disse:

outra coisa que eu acho engraçado é que em pascal e tudo junto

 

Não, não é. Implementation pode nem estar disponível porque por exemplo não se sabe sequer quem escreveu.

 

2 horas atrás, KXSY disse:

Quando você quiser se livrar do código e só usar o preprocessador

 

Muitas vezes você não tem o código. Até gostaria talvez, mas não tem. Mas você quer usar. Como chamar OpenGL a partir de seu programa Pascal para plotar aquele gráfico, ou usar wxPascal para usar as rotinas de wxWidgets e escrever interfaces gráficas portáveis para Linux e Windows...

 

2 horas atrás, KXSY disse:

Quando você passa de um código com mais de 15 mil linhas vai ver que ficar recompilando tudo que não precisa ser recompilado se torna uma má ideia

 

Exato. Imagine compilar as centenas de milhares de linhas de <stdlib.h> e <iostream.h> para aquele programa em  C++ que roda std::cout << "Hello World" << std::endl;

 

Continue escrevendo se ainda não ficou clara a mecânica da geração de código, IDE a parte.

 

  • Curtir 1
Postado
5 horas atrás, KXSY disse:

Eu pensei que ele queria saber como funciona a nível de código não a parte da compilação em si, por isso mencionei para utilizar o compilador na linha de comando

 

Você resumiu muito bem a questão: IDE é um problema nesse caso porque eu acho que raramente os instrutores explicam o que está sendo "integrado" ali...

5 horas atrás, KXSY disse:

De um jeito ou de outro ainda vai está lá, mas só não vai ser legível no caso de unidades pre-compiladas, e igual em C que resolve todas as ligações externas com o hearder e o linker cuida de ligar o código

Não, não vai: pense isso: Implementation e Interface só tem a ver com o compilador e programas fonte. Você pode não ter acesso a isso e em geral não tem mesmo. O fato de você incluir a implementação do código através de bibliotecas dinâmicas em tempo de execução ou bibliotecas estáticas na geração do executável não deixa você mais perto da tal Implementation que seria uma particular implementação do código que está usando. 

Em muitos casos você tem até mais de uma versão da mesma biblioteca e decide na hora do link qual vai gerar. E nunca viu a tal implementation. É assim em todas as linguagens.

 

 

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!