Click to See Complete Forum and Search --> : construction inline/offline


Rabelo
January 23rd, 2004, 02:30 PM
Hey guys

I am with a strange bug that I worked around but have never seen before:

If I put the construction code on the implementation file (.cpp) the bug appears, if I put it in the inteface file (.h) the bug dissapear...

the code is for interface file:

// ==== without the bug =====

class CNomeArquivo
{
string NomeCompleto,
EOTOrigem,
EOTDestino,
DiaMesAno,
HoraMinutoSegundo,
Sequencia,
Tipo;

unsigned short TAM_NOME_ARQUIVO;

public:

// === CNomeArquivo(string& Nome); just declared on implementation bug case

CNomeArquivo(string& Nome): NomeCompleto(Nome),
EOTOrigem(Nome.substr(6,3)),
EOTDestino(Nome.substr(9,3)),
DiaMesAno(Nome.substr(18,6)),
HoraMinutoSegundo(Nome.substr(26,6)),
Sequencia(Nome.substr(14,2)),
Tipo(Nome.substr(34,2)),
TAM_NOME_ARQUIVO(35) {};

int Consiste();

const string& PegaEOTOrigem() {return EOTOrigem;};
const string& PegaEOTDestino() {return EOTDestino;};
};

//=======================================
// Implementation, with the bug

#include "stdlib.h"
#include <string>

using namespace std;

#include "cnomearqt1.h"

CNomeArquivo::CNomeArquivo(string& Nome): NomeCompleto(Nome),
EOTOrigem(Nome.substr(6,3)),
EOTDestino(Nome.substr(9,3)),
DiaMesAno(Nome.substr(18,6)),
HoraMinutoSegundo(Nome.substr(26,6)),
Sequencia(Nome.substr(14,2)),
Tipo(Nome.substr(34,2)),
TAM_NOME_ARQUIVO(35) {};


int CNomeArquivo::Consiste()
{
/*
if (NomeCompleto.size() != TAM_NOME_ARQUIVO || NomeCompleto.substr(0,6) != string("TCOR.T") || NomeCompleto.substr(12,2) != string(".S") || NomeCompleto.substr(16,2) != string(".D") || NomeCompleto.substr(24,2) != string(".H"))
return false;

DiaMesAno.insert(0, substr(26,2) + substr(28,2)+ substr(30,2));
CData Data(DiaMesAno);

if (Data.ValidaData().size() != 25) return false;
*/
return true;
}


output :

hpux1004:/RABELO/ofc_cobill>rm *.o ; make
g++ -c -g -Wall cnomearqt1.cpp
g++ -c -g -Wall carqentradat1.cpp
g++ -c -g -Wall cdata.cpp
g++ -c -g -Wall ofc_cobill.cpp
g++ -g -D cnomearqt1.o carqentradat1.o cdata.o ofc_cobill.o -o ofc_cobill -lc -lm
/bin/ld: Unsatisfied symbols:
CNomeArquivo::CNomeArquivo(basic_string<char, string_char_traits<char>, __default_alloc_template<false, 0> > & )(first referenced in carqentradat1.o) (code)
collect2: ld returned 1 exit status
*** Error exit code 1

Stop.
hpux1004:bsqwrk15:/RABELO/ofc_cobill>



when the construction is in the implemetation file The constructor is just declared on the interface file.


Tks in advance

Rabelo

Paul McKenzie
January 23rd, 2004, 03:54 PM
Get rid of all of the other CPP's and modules. This is a linker error, so you should cut this down to its simplest form.

// here is MAIN.h
#ifndef MAIN_H
#define MAIN_H

#include <string>
class CNomeArquivo
{
std::string NomeCompleto,
EOTOrigem,
EOTDestino,
DiaMesAno,
HoraMinutoSegundo,
Sequencia,
Tipo;

unsigned short TAM_NOME_ARQUIVO;

public:

CNomeArquivo(const std::string& Nome);
int Consiste();

const std::string& PegaEOTOrigem() {return EOTOrigem;};
const std::string& PegaEOTDestino() {return EOTDestino;};
};
#endif

// MAIN.CPP
#include "main.h"

CNomeArquivo::CNomeArquivo(const std::string& Nome):
NomeCompleto(Nome),
EOTOrigem(Nome.substr(6,3)),
EOTDestino(Nome.substr(9,3)),
DiaMesAno(Nome.substr(18,6)),
HoraMinutoSegundo(Nome.substr(26,6)),
Sequencia(Nome.substr(14,2)),
Tipo(Nome.substr(34,2)),
TAM_NOME_ARQUIVO(35) {}

int main()
{
CNomeArquivo C("abc123");
}

Now you have just one module to link and test. This compiles and links successfully in VC++ 6.0.

A few things though

1) if your header file contains the string class, you should include <string> in your header. As a matter of fact, any classes that your header files use should include what it uses. This way your header file can stand alone and compile. Right now, you are including string outside your header file, which makes your header file give errors if you forget to include <string> in my CPP files.

2) The header file should use the namespace names, and not rely on the enclosing CPP module to state "using namespace std". Again, for the same reasons as 1).

3) Note the use of const std::string& for the constructor parameter. This makes me able to pass "abc123" to the constructor, not just std::string types.

Regards,

Paul McKenzie

CornedBee
January 25th, 2004, 07:52 AM
Doesn't gcc care about the order the files are passed on the command line? Try fiddling with that.

Rabelo
January 26th, 2004, 08:40 AM
Paul,

I implemented all your changes and the bug persists. I also discovered that any function I put on the implementation file this error occurs on it, no matter what it does. I solved the problem putting all functions in .H file. So my .CPPfile is only with he includes. For a while it is working because these function are smalls and can be on line. On the error lines is visible that the compiler is taking the function as a string::function not as CNomeArquivo::function.

Thank you.


Rabelo