Rozdzielenie programu na kilka plików

0

Mam taki kod:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <time.h>
#include <vector>
#include "Test.h"
#include "Freq.h"
#include "History.h"

int main()
{
    srand( time( NULL ) );

    Freq f1;

    int again;

    f1.create_file();
    f1.user_data();
    system("cls");

poczatek:
        f1.menu();
        switch(f1.liczba)
        {

        case 1:
        {
            Funkcja case 1();
break;
        }

        case 2:
        {
            Funkcja case 2();
break;
        }

        case 3:
        {
            f1.load_file();
            f1.wyswietl();
            f1.Vector.clear();
            break;
        }
        case 4:
        {
            system("pause");
            return 0;
        }

        }

        std::cout<<std::endl<<"Wrocic do menu? (1.Tak  2.Nie): ";
        std::cin>>again;
        system("cls");
    if(again==1)
        goto poczatek;
    else
    system("pause");
    return 0;
}
 

To jest main, a poniżej wklejam nagłówkowy, Freq i Test.

 #ifndef FREQ_H__
#define FREQ_H__
#include "Test.h"

class Freq :public Test
{
public:
    int* liczba_octave;
    int* liczba_terce;
    int* liczba_another;
    int record_number;

    Freq(int r_n=0, int n_a=5, int d_l=0) :Test(n_a=5, d_l=0)
    {
        number_attempts=n_a;
        diff_level=d_l;
        liczba_octave = new int[n_a];
        liczba_terce = new int[n_a];
        liczba_another = new int[n_a];
        record_number=r_n;
    }

    ~Freq()
    {
        delete [] liczba_octave;
        delete [] liczba_terce;
        delete [] liczba_another;
    }

     void select_octave();
     void select_terce();
     void select_freq2();
     void genere_base();
     void genere_freq();
     void genere_freq2();
     void higher_lower();
};

#endif // FREQ_H__
#ifndef TEST_H__
#define TEST_H__
class Test
{
    //protected:
        public:
    int number_attempts;
    int diff_level;
    int high_low;
    int good;
    int liczba;
    int answer;
    int correct;
    int points;


    Test(int n_a=5, int d_l=0, int l=0, int h_l=0, int p=0, int g=0, int a=0, int c=0)
    {
        number_attempts=n_a;
        diff_level=d_l;
        high_low=h_l;
        good=g;
        answer=a;
        correct=c;
        points=p;
        liczba=l;
    }
    virtual ~Test() {}

    void load_number_att();
    void take_answer();
    void check();
    void show_points();
    void menu();
    void how_can_freq();

    virtual void genere_freq()=0;
    virtual void genere_freq2()=0;
    virtual void genere_base()=0;
    virtual void select_octave()=0;
    virtual void select_terce()=0;
    virtual void select_freq2()=0;
    virtual void higher_lower()=0;
    virtual void create_file()=0;
    virtual void take_record()=0;
    virtual void save_file()=0;
    virtual void load_file()=0;
    virtual void user_data()=0;
};

#endif // TEST_H__
 

W mainie w linijce w które tworzę obiekt typu Freq, o nazwie f1 dostaje następujący błąd:

 15|error: cannot declare variable `f1' to be of type `Freq'|

O co może chodzić? Nie mogę do tego dojść...

0

Test ma ileś tam czysto wirtualnych metod, Freq nie implementuje wszystkich, przez co jest klasą abstrakcyjną i nie można tworzyć obiektu tej klasy.

0

Implementowanie tych virtualnych metod do Freq jest chyba niedobrym rozwiązaniem.
Czy jest jakiś prostu sposób rozwiązania tego problemu?

Jezeli tworze ten obiekt typu Test to dostaje kolejna mase bledow:

||=== Build: Debug in podzxielone (compiler: GNU GCC Compiler) ===|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp||In function `int main()':|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|16|error: cannot declare variable `f1' to be of type `Test'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|16|error:   because the following virtual functions are abstract:|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|54|error:  virtual void Test::wyswietl()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|53|error:  virtual void Test::user_data()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|52|error:  virtual void Test::load_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|51|error:  virtual void Test::save_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|50|error:  virtual void Test::create_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|48|error:  virtual void Test::higher_lower()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|47|error:  virtual void Test::select_freq2()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|46|error:  virtual void Test::select_terce()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|45|error:  virtual void Test::select_octave()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|44|error:  virtual void Test::genere_base()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|43|error:  virtual void Test::genere_freq2()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|42|error:  virtual void Test::genere_freq()|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|39|error: 'class Test' has no member named 'record_number'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|48|error: 'class Test' has no member named 'liczba_octave'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|57|error: 'class Test' has no member named 'liczba_terce'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|73|error: 'class Test' has no member named 'record_number'|
||=== Build failed: 18 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

Gdybym podzielil role pomiedzy dwa obiekty to program wtedy mi sie sypie..

A gdy f1 jest typu Freq to dostaje coś takiego:

||=== Build: Debug in podzxielone (compiler: GNU GCC Compiler) ===|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp||In function `int main()':|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|16|error: cannot declare variable `f1' to be of type `Freq'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|16|error:   because the following virtual functions are abstract:|
C:\Users\staniuu\Desktop\Podzielone na pliki\Freq.h|38|error:  virtual void Freq::create_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Freq.h|39|error:  virtual void Freq::save_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Freq.h|40|error:  virtual void Freq::load_file()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Freq.h|41|error:  virtual void Freq::user_data()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Freq.h|42|error:  virtual void Freq::wyswietl()|
||=== Build failed: 7 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

Jak miałem wszystko w jednym pliku .cpp to działało bez zarzutów.

zamiana znaczników <code class="cpp"> na <code class="none"> - @furious programming

0

To jest problem projektowy. Masz metody czysto wirtualne w Test, ale nie możesz ich implementować w Freq. To oznacza, że Freq nie powinno dziedziczyć po Test. To jak jakbyś dziedziczył Auto po Samolot, a potem mówił: Auto nie może implementować lataj(), co mam robić?

Jak miałem wszystko w jednym pliku .cpp to działało bez zarzutów.
Śmiem wątpić.

0

Sam zobacz: (kompilator minGW)

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <windows.h>
#include <fstream>
#include <time.h>
#include <vector>

class Test
{
public:
    int number_attempts;
    int diff_level;
    int high_low;
    int good;
    int liczba;
    int answer;
    int correct;
    int points;
    int which_attempt;
    int Vec_size;
    std::vector <std::string> Vector;
    std::string name;
    std::string data;

    Test(int n_r=5, int d_l=0, int h_l=0, int l=0, int g=0, int a=0, int c=0, int p=0, int w_a=0, int V_s=0, std::string n="default", std::string d="00.00.0000")
    {
        number_attempts=n_r;
        diff_level=d_l;
        high_low=h_l;
        good=g;
        answer=a;
        correct=c;
        points=p;
        which_attempt=w_a;
        liczba=l;
        Vec_size=V_s;
        name=n;
        data=d;

    }
    virtual ~Test() {};

    virtual void genere_freq()=0;
    virtual void genere_freq2()=0;
    virtual void genere_base()=0;
    virtual void select_octave()=0;
    virtual void select_terce()=0;
    virtual void select_freq2()=0;
    virtual void higher_lower()=0;


    void user_data()
    {
        std::cout<<"Podaj nazwe: ";
        std::cin>>name;
        time_t data;
        time(&data);
        ctime(&data);

    }

    void load_number_att()
    {
        std::cout<<"Podaj ilosc prob: ";
        std::cin>>number_attempts;
    }

    void take_answer()
    {
        std::cout<<"Podaj odpowiedz: ";
        std::cin>>answer;
    }

    void check()
    {
        if(answer==correct)
        {
            std::cout<<"Dobrze!"<<std::endl;
            points++;
        }
        else if (answer != correct)
        {
            std::cout<<"Zle!"<<std::endl;
        }
    }

    void show_points()
    {
        std::cout<<"Zdobyte punkty: "<<points<<std::endl;
    }

    void menu()
    {
        std::cout<<"1. Test z wybieraniem jednej czestotliwosci."<<std::endl;
        std::cout<<"2. Test z porownywaniem dwoch czestotliwosci."<<std::endl;
        std::cout<<"3. Historia."<<std::endl;
        std::cout<<"4. Koniec."<<std::endl;
        std::cout<<std::endl<<"Twoj wybor: ";
        std::cin>>liczba;
    }

    void how_can_freq()
    {
        std::cout<<"Podaj poziom trudnosci (tercje = 1, oktawy = 0): ";
        std::cin>>diff_level;

        if(diff_level==0)
            std::cout<<"Czestotliwosci do wyboru: 125, 250, 500, 1000, 2000, 4000, 8000, 16000";
        else if(diff_level==1)
        {
            std::cout<<"Czestotliwosci do wyboru: 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000"<<std::endl;
            std::cout<<"1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000"<<std::endl;
        }
    }

    void create_file()
    {
        std::ofstream plik( "history.txt", std::ios::app);
    }

    void save_file()
    {
        std::fstream plik;
        plik.open("history.txt", std::ios::out | std::ios::app);
        if( plik.good() )
        {
            plik<<__DATE__<<"       ";
            plik<<liczba<<"                  ";
            plik<<diff_level<<"                 ";
            plik<<points<<"         ";
            plik<<name<<std::endl;

        }
        plik.close();
    }

    void load_file()
    {
        std::fstream plik;
        plik.open("history.txt", std::ios::in);
        if(plik.good()==false)
        {
            std::cout<<"Nie udalo sie otworzyc pliku!";
            exit(0);
        }

        std::string linia;

        while(getline(plik,linia))
        {
            Vector.push_back(linia);
        }
        plik.close();
    }

    void wyswietl()
    {
        std::cout<<"   Data   "<<"   Numer Testu   "<<"   Poziom Trudnosci   "<<"   Punkty   "<<"   Nazwa   "<<std::endl;
        std::vector < std::string >::iterator it_Vec = Vector.begin();
        for( ; it_Vec != Vector.end(); it_Vec++ )
            std::cout<<* it_Vec<<std::endl;
    }
};

class Freq :public Test
{
public:
    int* liczba_octave;
    int* liczba_terce;
    int* liczba_another;
    int record_number;

    Freq(int r_n=0, int n_r=5, int d_l=0) :Test(n_r=5, d_l=0)
    {
        number_attempts=n_r;
        diff_level=d_l;
        liczba_octave = new int[n_r];
        liczba_terce = new int[n_r];
        liczba_another = new int[n_r];
        record_number=r_n;
    }

    ~Freq()
    {
        delete [] liczba_octave;
        delete [] liczba_terce;
        delete [] liczba_another;
    }

    virtual void select_octave()
    {
        int octave[8] =  {125, 250, 500, 1000, 2000, 4000, 8000, 16000};

        for(int i = 0 ; i < number_attempts; i++)
        {
            int rand_octave = ( rand () % 8);

            for( int j = 0 ; j <= rand_octave ; j++)
            {
                if(j==rand_octave)
                    liczba_octave[i]=octave[j];
            }
        }
    }

    virtual void select_terce()
    {
        int terce[22] = {125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500, 16000};

        for(int i = 0 ; i < number_attempts; i++)
        {
            int rand_terce = ( rand () % 22);

            for( int j = 0 ; j <= rand_terce ; j++)
            {
                if(j==rand_terce)
                    liczba_terce[i]=terce[j];
            }
        }
    }

    virtual void select_freq2()
    {
        int another[4] =  { 436, 438, 442, 444};

        {
            for(int i = 0 ; i < number_attempts; i++)
            {
                int rand_another = ( rand () % 4);

                for ( int t = 0 ; t <= rand_another ; t++)
                {
                    if(liczba_another[t]==another[rand_another])
                        do
                        {
                            rand_another = ( rand () % 4);
                        }
                        while(liczba_another[t] != another[rand_another]);
                }

                for( int j = 0 ; j <= rand_another ; j++)
                {
                    if(j==rand_another)
                        liczba_another[i]=another[j];
                }
            }
        }
    }

    virtual void genere_base()
    {
        Beep(440,3000);
    }

    virtual void genere_freq()
    {
        if(diff_level==0)
        {
            correct=liczba_octave[record_number];
            Beep(liczba_octave[record_number],3000);
        }
        else if(diff_level==1)
        {
            correct=liczba_terce[record_number];
            Beep(liczba_terce[record_number],3000);
        }
    }

    virtual void genere_freq2()
    {
        correct=liczba_another[record_number];
        Beep(liczba_another[record_number],3000);
    }

    virtual void higher_lower()
    {
        std::cout<<std::endl<<"Wygenerowana czestotliwosc byla wyzsza[1] czy nizsza[0]?: ";
        std::cin>>high_low;

        if(correct<=440)
        {
            good = 0;
        }
        else if(440<=correct)
        {
            good = 1;
        }

        if(high_low==good)
        {
            std::cout<<"Dobrze!"<<std::endl;
            points++;
        }
        else if(high_low != good)
        {
            std::cout<<"Zle!"<<std::endl;
        }
    }
};

int main()
{
    srand( time( NULL ) );

    Freq f1;

    int again;

    f1.create_file();
    f1.user_data();
    system("cls");

poczatek:
    f1.menu();
    switch(f1.liczba)
    {

    case 1:
    {
        f1.load_number_att();
        f1.how_can_freq();
        if(f1.diff_level==0)
            f1.select_octave();
        else if(f1.diff_level==1)
            f1.select_terce();
        for(int i = 0 ; i < f1.number_attempts ; i++)
        {
            f1.record_number = i;

            if(f1.diff_level==0)
            {
                std::cout<<std::endl<<"Czestotliwosc numer: "<<i+1<<std::endl;
                f1.genere_freq();
                f1.take_answer();
                f1.check();
                std::cout<<"Wygenerowana czestotliwosc to: ";
                std::cout<<f1.liczba_octave[i]<<std::endl;
            }
            else if(f1.diff_level==1)
            {
                std::cout<<std::endl<<"Czestotliwosc numer: "<<i+1<<std::endl;
                f1.genere_freq();
                f1.take_answer();
                f1.check();
                std::cout<<"Wygenerowana czestotliwosc to: ";
                std::cout<<f1.liczba_terce[i]<<std::endl;
            }
            Sleep(500);
        }
        f1.show_points();
        f1.save_file();
        f1.points=0;
        break;
    }

    case 2:
    {
        f1.load_number_att();
        f1.select_freq2();
        for(int i = 0 ; i < f1.number_attempts ; i++)
        {
            f1.record_number = i;
            std::cout<<std::endl<<"Zestaw czestotliwosci numer: "<<i+1<<std::endl;
            Sleep(1500);
            std::cout<<"Czestotliowsc podstawowa 440Hz";
            for( int y = 0 ; y <= 3 ; y++)
            {
                std::cout<<".";
                Sleep(500);
            }
            f1.genere_base();
            std::cout<<std::endl<<"Czestotliowsc odstrojona";
            for( int y = 0 ; y <= 3 ; y++)
            {
                std::cout<<".";
                Sleep(500);
            }
            Sleep(1500);
            f1.genere_freq2();
            f1.higher_lower();
            Sleep(1000);
        }
        f1.show_points();
        f1.save_file();
        f1.points=0;
        break;
    }

    case 3:
    {
        f1.load_file();
        f1.wyswietl();
        f1.Vector.clear();
        break;
    }
    case 4:
    {
        system("pause");
        return 0;
    }

    }

    std::cout<<std::endl<<"Wrocic do menu? (1.Tak  2.Nie): ";
    std::cin>>again;
    system("cls");
    if(again==1)
        goto poczatek;
    else
        system("pause");
    return 0;
}

 
1

W jednej wersji masz 7 czysto wirtualnych metod w Test, a w drugiej 12, więc śmiem twierdzić, że te kody nie są równoważne.

1

zobrazuje slowa @twonek

pierwszy post

    virtual void genere_freq()=0;
    virtual void genere_freq2()=0;
    virtual void genere_base()=0;
    virtual void select_octave()=0;
    virtual void select_terce()=0;
    virtual void select_freq2()=0;
    virtual void higher_lower()=0;
    virtual void create_file()=0;
    virtual void take_record()=0;
    virtual void save_file()=0;
    virtual void load_file()=0;
    virtual void user_data()=0; 

ostatni post

    virtual void genere_freq()=0;
    virtual void genere_freq2()=0;
    virtual void genere_base()=0;
    virtual void select_octave()=0;
    virtual void select_terce()=0;
    virtual void select_freq2()=0;
    virtual void higher_lower()=0; 
0
 virtual void create_file()=0;
    virtual void take_record()=0;
    virtual void save_file()=0;
    virtual void load_file()=0;
    virtual void user_data()=0; 

Dodałem to bo kompilator płakał że takie funkcje nie istnieją.
Ale ok, usunąłem to podzieliłem role pomiędzy 2 obiekty, Jeden jest typu Freq, drugi History.
Po usunięciu funkcji virutalnych z Test.h program się kompiluje tylko kiedy dana funkcja ma zostać wywołana, wywołana nie zostaje. To oczywiste przecież Test który zarządza przebiegiem Testu o niej nie wie. Więc deklaruje w Tescie coś takiego:

    virtual void select_octave()=0;
    virtual void select_terce()=0;
    virtual void select_freq2()=0;
    virtual void genere_base()=0;
    virtual void genere_freq()=0;
    virtual void genere_freq2()=0;
    virtual void higher_lower()=0;
 

Dostaje następujące błędy:

||=== Build: Debug in podzxielone (compiler: GNU GCC Compiler) ===|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp||In function `int main()':|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|22|error: cannot declare variable `h1' to be of type `History'|
C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp|22|error:   because the following virtual functions are abstract:|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|37|error:  virtual void Test::select_octave()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|38|error:  virtual void Test::select_terce()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|39|error:  virtual void Test::select_freq2()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|40|error:  virtual void Test::genere_base()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|41|error:  virtual void Test::genere_freq()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|42|error:  virtual void Test::genere_freq2()|
C:\Users\staniuu\Desktop\Podzielone na pliki\Test.h|43|error:  virtual void Test::higher_lower()|
||=== Build failed: 9 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|
 

Czyli klasa History nie wie co to są za funkcje, nawet jak dam je private to dostaje ten sam błąd.
Rozumiem że gdyby klasa History nie dziedziczyła po Test to nie byłoby problemu?
Sęk w tym że dostaje od niej dane do zapisu.
Mogę te dane przekazać jakoś w mainie?

0

Ja w kwestii językowej:

        delete [] liczba_terce;

po pierwsze nie powinieneś nazywać zmiennych w dwóch językach na raz, ale co do słowa “terce”, to mimo że tłumaczy się na polskie „tercja”, to nie o taką tercję chyba tobie chodzi.

http://en.wikipedia.org/wiki/Terce
http://en.wikipedia.org/wiki/Major_third

2
void create_file()
{
    std::ofstream plik( "history.txt", std::ios::app);
}

Zjadłeś nazwę klasy, przez co zdefiniowałeś funkcję, która nie należy do żadnej klasy.

Czyli klasa History nie wie co to są za funkcje, nawet jak dam je private to dostaje ten sam błąd.
NIE. Kompilator mówi, że nie może stworzyć obiektu klasy History, bo nie implementuje wszystkich czystych metod wirtualnych (klasy bazowej), przez co jest abstrakcyjna.

0

Ale jak dodam do klasy History coś takiego:

virtual void select_octave();
    virtual void select_terce();
    virtual void select_freq2();
    virtual void genere_base();
    virtual void genere_freq();
    virtual void genere_freq2();
    virtual void higher_lower() 

To dostaje taki błąd:

C:\Users\staniuu\Desktop\Podzielone na pliki\main.cpp||undefined reference to `vtable for History'|
 
0

A masz definicje do nich? Bo same deklaracje to jeszcze nie jest implementacja.

0

No ale co mam w nich zdefiniować?
Jak przypiszę 0 to nie moge stworzyc nowego obiektu...
A nie chce mieć w 2 klasach tego samego kodu, rozdzieliłem je aby było czytelniej.
Rozumiem że połączenie klas Test i History rozwiaze problem, ale wolałbym tego nie robić.

1

A po co te metody są w Test? To jest funkcjonalność Freq, więc bez sensu jest deklaracja tych metod jako czysto wirtualnych w Test.

Poza tym odnoszę wrażenie, że dziedziczenie Freq po Test to też jakaś herezja. Czy Freq jest Testem? Czy History jest Testem? Jeśli odpowiedź gdzieś brzmi "nie", to tam nie powinno być dziedziczenia.

0

No jak wywalę te metody z Test to się kompiluje ale klasa Test w trakcie działania programu nie używa tych metod, czyli nie uzupełnia tablicy wartościami oraz ich nie generuje.
Freq musi dziedziczyć po Test ponieważ dostaje tam wartość jak duża utworzyć ma tablice.
Freq jest Testem, History nie jest testem, History zapisuje i odczytuje tylko dane z pliku.

1
staniuu napisał(a):

Freq musi dziedziczyć po Test ponieważ dostaje tam wartość jak duża utworzyć ma tablice.

Nie, to jest kiepski powód, żeby dziedziczyć. Freq powinien mieć metodę, która przyjmuje i zapisuje potrzebne wartości.

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