Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Problem z podziałem projektu na pliki

Ostatnio zmodyfikowano 2014-11-19 22:28
Autor Wiadomość
worn
Temat założony przez niniejszego użytkownika
[C++] Problem z podziałem projektu na pliki
» 2014-11-19 18:26:22
Starałem się podzielić swój projekt na kilka plików, aby poprawić czytelność kodu. Wszystko w sumie szło dosyć sprawnie aż do pewnego momentu. Problem ze zmienną. Co by nie pisać długich historyjek na ten temat, to przejdę od razu do rzeczy.

main.cpp
C/C++
#include <iostream>
#include <string>

#include "menu.hpp"

using namespace std;

void main() {
    menu();
}

menu.cpp - to w tym pliku występują problemy z kompilacją
C/C++
#include <iostream>

#include "menu.hpp"
#include "kursanci.hpp"

using namespace std;

void menu() {
    bool flag = true;
    int option = 0, temp, value;
    char d;
    do {
        value = 0;
        system( "cls" );
        cout << "\t\t\t\t\tMENU" << endl << endl;
        if( option == 0 ) {
            cout << "1. Zarzadzanie kursantami." << endl;
            cout << "4. Ustawienia." << endl;
            cout << "9. Wyjscie." << endl;
        }
        switch( option ) {
        case 1:
            cout << "1. Dodaj kursanta." << endl;
            cout << "2. Wyswietl kursantow." << endl;
            cout << "3. Usun kursanta." << endl;
            cout << "4. Usun kursantow." << endl;
            cout << "0. Cofnij." << endl;
            cout << "9. Wyjscie." << endl;
            break;
        case 11:
            createKursanci( Kursanci, nK );
            nK++;
            flag = false;
            break;
        case 12:
            if( nK ) {
                for( int i = 0; i < nK; i++ )
                     Kursanci[ i ]->get(); // tutaj występuje problem z kompilacją
               
            } else {
                cout << "Nie ma zadnych kursantow w bazie." << endl << endl;
            }
            system( "pause" );
            flag = false;
            break;
        case 13:
            if( nK ) {
                for( int i = 0; i < nK; i++ ) {
                    cout << "#" << i << endl;
                    Kursanci[ i ]->get(); // tutaj występuje problem z kompilacją
                }
                cout << endl << "Wybierz kursanta do usuniecia: ";
                cin >> value;
                cout << "Czy na pewno chcesz usunac danego kursanta?" << endl << "[T/N]: ";
                cin >> d;
                if( d == 't' || d == 'T' ) {
                    deleteKursanci( Kursanci, nK, value );
                    nK--;
                }
            } else {
                cout << "Nie ma zadnych kursantow w bazie." << endl << endl;
                system( "pause" );
            }
            flag = false;
            break;
        case 14:
            if( nK ) {
                cout << "Czy na pewno chcesz usunac wszystkich kursantow?" << endl << "[T/N]: ";
                cin >> d;
                if( d == 't' || d == 'T' ) {
                    deleteKursanci( Kursanci, nK );
                    nK = 0;
                }
            } else {
                cout << "Nie ma zadnych kursantow w bazie." << endl << endl;
                system( "pause" );
            }
            flag = false;
            break;
        }
        temp = option * 10;
        if( flag ) {
            cout << endl << "Wybierz opcje: ";
            cin >> option; // AV
        } else {
            option = 0;
            flag = true;
        }
        if( option == 0 ) option = temp / 100;
        else if( option != 9 ) option += temp;
       
    } while( option != 9 );
   
}

kursanci.hpp
C/C++
#ifndef kursanci_hpp
#define kursanci_hpp

class kursanci;
kursanci ** Kursanci;
int nK;
void createKursanci( kursanci *& );
void createKursanci( kursanci **&, int );
void deleteKursanci( kursanci *& );
void deleteKursanci( kursanci **&, int );
void deleteKursanci( kursanci **&, int, int );

#endif

kursanci.cpp
C/C++
#include <iostream>
#include <string>

using namespace std;

class kursanci {
    string pImie;
    string dImie;
    string nazwisko;
public:
    void get();
};

void createKursanci( kursanci *& a ) {
    a = new kursanci;
    a->set();
}
void createKursanci( kursanci **& a, int n ) {
    kursanci ** temp = new kursanci *[ n + 1 ];
    if( n > 0 ) {
        for( int i = 0; i < n; i++ )
             temp[ i ] = a[ i ];
       
        createKursanci( temp[ n ] );
        delete[] a;
    } else {
        createKursanci( temp[ n ] );
        delete[] a;
    }
    a = temp;
}
void deleteKursanci( kursanci *& a ) {
    delete a;
    a = 0;
}
void deleteKursanci( kursanci **& a, int n ) {
    for( int i = 0; i < n; i++ )
         deleteKursanci( a[ i ] );
   
    delete[] a;
    a = 0;
}
void deleteKursanci( kursanci **& a, int n, int index ) {
    kursanci ** temp = new kursanci *[ n - 1 ];
    int k = 0;
    for( int i = 0; i < n; i++ )
    if( i != index ) {
        temp[ k ] = a[ i ];
        k++;
    }
    delete[] a;
    a = temp;
    n--;
}

void kursanci::get() {
    cout << "Pierwsze Imie: " << pImie << endl;
    cout << "Drugie Imie: " << dImie << endl;
    cout << "Nazwisko: " << nazwisko << endl << endl;
}

Log kompilatora:

menu.cpp(42): error C2027: use of undefined type 'kursanci'
kursanci.hpp(4) : see declaration of 'kursanci'
menu.cpp(42): error C2227: left of '->get' must point to class/struct/union/generic type
menu.cpp(53): error C2027: use of undefined type 'kursanci'
kursanci.hpp(4) : see declaration of 'kursanci'
menu.cpp(53): error C2227: left of '->get' must point to class/struct/union/generic type

Skróciłem kod do najważniejszych elementów, żebyście nie musieli analizować kilometrów nic nie znaczącego kodu. Jedyna rzecz, którą znalazłem w necie i wydaje mi się, że dotyczy mojego problemu, znajduje się tutaj: http://stackoverflow.com​/questions/553682​/when-can-i-use-a-forward-declaration
Tylko nie wiem co z tym dalej począć. :(

Pozdrawiam :)
P-120995
Monika90
» 2014-11-19 18:50:01
Typowo, definicje klas, czyli to:
C/C++
class kursanci {
    string pImie;
    string dImie;
    string nazwisko;
public:
    void get();
};
daje się w pliku nagłówkowym,

a definicje zmiennych globalnych:
C/C++
kursanci ** Kursanci;
int nK;
w pliku cpp, w hpp tylko ich deklaracje

Poza tym funkcja main ma zwracać typ int.
P-120996
worn
Temat założony przez niniejszego użytkownika
» 2014-11-19 21:48:48
Dzięki za odpowiedź :)
Zastosowałem się do wskazówek i mam teraz kolejny problem. Linker zwraca mi coś takiego:
1>menu.obj : error LNK2005: "class kursanci * * Kursanci" (?Kursanci@@3PAPAVkursanci@@A) already defined in kursanci.obj
1>menu.obj : error LNK2005: "int nK" (?nK@@3HA) already defined in kursanci.obj

Z tego co się zorientowałem, to problem taki występuje w sytuacji, gdy dołączam do kilku plików źródłowych te same pliki nagłówkowe i rzeczywiście tak robię.

W pliku menu.cpp
C/C++
#include <iostream>

#include "kursanci.hpp"
#include "instruktorzy.hpp"

kursanci.cpp
C/C++
#include <iostream>
#include <string>

#include "kursanci.hpp"

Tylko, że jak z któregokolwiek wyrzucę dyrektywę
#include "kursanci.hpp"
, to zwraca potem mi błędy podobne do tych, o których wspominałem w pierwszym poście.

Pozdrawiam :)
P-121027
Monika90
» 2014-11-19 21:58:45
Masz w pliku nagłówkowym definicje zmiennych globalnych. Przenieś te definicje do jednego z plików cpp, a w pliku nagłówkowym zostaw tylko deklaracje.

Definicje wyglądają tak:
C/C++
kursanci ** Kursanci;
int nK;

a deklaracje wyglądają tak:
C/C++
extern kursanci ** Kursanci;
extern int nK;

P-121029
worn
Temat założony przez niniejszego użytkownika
» 2014-11-19 22:28:15
Dzięki wielkie za pomoc, już wszystko działa.

Pozdrawiam :)
P-121032
« 1 »
  Strona 1 z 1