Klasy w C++ - undefined reference

0

Piszę w Qt coś jak menadżer plików *.ini wszystko jest zamknięte w klasie:

namespace FNC
{

class IniFile
{
public:
    IniFile();
    void Open( QString FileName );
    void Save( QString FileName );
    QString GetValue( QString Section, QString Key );
    void WriteValue( QString Section, QString Key, QString Value = "=EMPTY=");
    QString GetSectionsNames( QString separator );
    QString GetKeysNames( QString Section, QString separator );

private:
    QStringList Sections;
    QStringList Keys;
    QStringList Values;

    QString EMPTY();

};

}

a to definicje funkcji:

using namespace FNC;

QString ini(QString c)
{
    return FNC::Coder::Text2FNI( c, FNC::Ini );
}

IniFile::IniFile()
{

}

void IniFile::Open( QString FileName )
{
    QFile file(FileName);
    if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) return;
    QTextStream ts(&file);

    QString line, lastSection;
    for(; line != "end"; line = FNC::Coder::FNI2Text( ts.readLine(), FNC::Ini ) )
    {
        if(line.isEmpty()) continue;
        if(line[0] == '#') continue;

        if( line[0] == '[' )
        {
            line.remove( QChar('['), Qt::CaseInsensitive );
            line.remove( QChar(']'), Qt::CaseInsensitive );
            Sections << line;
            lastSection = line;
            Keys << EMPTY();
            Values << EMPTY();
        }
        else
        {
            line.replace( QString("="), QString(" ") );
            QStringList podzial = line.split( QRegExp("\\W+"), QString::SkipEmptyParts );
            Sections << lastSection;
            Keys << podzial.at(0);
            Values << podzial.at(0);
        }

        line.clear();
    }
}

void IniFile::Save( QString FileName )
{
    QFile open( FileName );
    open.open( QIODevice::WriteOnly | QIODevice::Text );
    QTextStream ts(&open);

    QString LastSection = Sections.at(0);
    ts << ini("[") << ini(LastSection) << ini("]") << "\n";
    for( int i = 0; i < Sections.size(); ++i )
    {
        if( Sections.at(i) != LastSection )
        {
            ts << ini("[") << ini(Sections.at(i)) << ini("]") << "\n";
        }
        else
        {
            ts << ini(Keys.at(i)) << ini("=") << ini(Values.at(i)) << ini("\n");
        }
    }
    ts << ini("end");
    open.close();
}

QString IniFile::GetValue( QString Section, QString Key )
{
    QString Return;
    for( int i = 0; i < Section.size(); ++i )
    {
        if( Sections.at(i) == Section && Keys.at(i) == Key ) Return = Values.at(i);
        else continue;
    }
    if( Return.isEmpty() ) return EMPTY();
    else return Return;
}

void IniFile::WriteValue( QString Section, QString Key, QString Value )
{
    if( GetValue( Section, Key ) != EMPTY() ) // Jezeli istnieje
    {
        for( int i = 0; i < Sections.size(); ++i )
        {
            if( Sections.at(i) == Section && Keys.at(i) == Key )
            {
                Values.removeAt(i);
                Values.insert( (i-1), Value );
            }
        }
    }
    else
    {
        QStringList newSections, newKeys, newValues;
        QString LastSection = Sections.at(0);
        int i = 0;
        for( ; i < ( Sections.size()+1 ); ++i )
        {
            if( Sections.at(i) != Section )
            {
                newSections << Sections.at(i);
                newKeys << Keys.at(i);
                newValues << Values.at(i);
                LastSection = Sections.at(i);
            }
            else
            {
                newSections << LastSection;
                newKeys << Key;
                newValues << Value;
                ++i;
            }
            ++i;
        }

        Sections.clear();
        Keys.clear();
        Values.clear();

        for( int j = 0; j < newSections.size(); ++j )
        {
            Sections << newSections.at(i);
            Keys << newKeys.at(i);
            Values << newValues.at(i);
        }
    }
}

QString IniFile::GetSectionsNames(QString separator)
{
    return Sections.join( separator );
}

QString IniFile::GetKeysNames(QString Section, QString separator)
{
    QString Return;
    for( int i = 0; i < Sections.size(); ++i )
    {
        if( Sections.at(i) == Section )
            Return += ( Keys.at(i) + separator );
    }
    return Return;
}

QString IniFile::EMPTY()
{
    return QString("=EMPTY=");
}

Wiem że są tutaj niepotrzebne funkcje i wgl ale po prostu chce nauczyć sie używania klas. Mój problem polega na tym że kiedy wywołuje w projekcie

FNC::IniFile ini;
ini.Open("Ini.ini");

itd. To zawsze wyrzuca mi błędy:

'C:\Users...\manager.cpp:-1: błąd: undefined reference to FNC::IniFile::IniFile()' 'C:\Users\...\manager.cpp:-1: błąd: undefined reference to FNC::Open(QString)'
'C:\Users...\manager.cpp:-1: błąd: undefined reference to FNC::IniFile::GetSectionsNames(QString)' 'C:\Users\...\manager.cpp:-1: błąd: undefined reference to FNC::GetValue(QString, QString)'
'C:\Users...\manager.cpp:-1: błąd: undefined reference to FNC::IniFile::GetValue(QString, QString)' ':-1: błąd: release/manager.o: bad reloc address 0x20 in section .text$_ZN7QStringD1Ev[__ZN7QStringD1Ev]'
'collect2.exe:-1: błąd: error: ld returned 1 exit status'

I nie ważne w jakim środowisku piszę (Code::Blocks, Qt Creator) to zawsze wyrzuca mi te błędy. Nagłówki są dołączone, prubowałem z

extern "C" { /*...*/ }

ale też nie działa :c

1

nagłówki jak nagłówki, ale czy plik .cpp z definicjami funkcji jest w projekcie?
i czy po dodaniu plików zrobiłeś qmake?

0

Pliki *.cpp są w projekcie ale nie wiem co to naczy zrobić qmake :d Ale wiem że to od Qt a ten problem zawsze się pojawia, nieważne w jakim środowisku programuje jakąkolwiek klase.

0

pod Qt Creatorem jest Build|Run qmake.
Nie wiem jak w innych IDE.

1

Ogólnie, fajnie.. ale nie wiem czy już czytałeś o użyciu klasy QSettings. Ona ma możliwość parsowania plików *.ini do odczytu i zapisu oraz można jej podać plik na którym ma pracować. Czy przypadkiem nie wynajdujesz koła? Ale jeśli o to chodzi by wynajdować lub się czegoś nauczyć to ok, nie mam uwag :-)

EDIT:
Przepraszam.. właśnie doczytałem że robisz to ćwiczebnie.. niemniej jednak zerknij do dokumentacji QSettings...

0

Udało mi się naprawić, problem polegał na tym że źle dołączyłem do siebie pliki (

#include <>

)


Mokrowski napisał(a):

Ogólnie, fajnie.. ale nie wiem czy już czytałeś o użyciu klasy QSettings. Ona ma możliwość parsowania plików *.ini do odczytu i zapisu oraz można jej podać plik na którym ma pracować. Czy przypadkiem nie wynajdujesz koła? Ale jeśli o to chodzi by wynajdować lub się czegoś nauczyć to ok, nie mam uwag :-)

Dziękuje przyda się mi bardzo :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1