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

Kompilowanie w visualu

Ostatnio zmodyfikowano 2018-06-03 15:06
Autor Wiadomość
MeehoweCK
Temat założony przez niniejszego użytkownika
Kompilowanie w visualu
» 2018-06-03 14:29:22
Cześć
Napisałem taki oto kod (dla celów szkoleniowych), który działa bez zarzutu dla kompilatora gnu. Problem w tym, że wykładowca życzy sobie, aby działał pod visualem, a tam pojawia się jakiś błąd i to nawet nie w fazie kompilacji, ale już przy wypisaniu na konsolę.

C/C++
#include <string>
#include <iostream>

using namespace std;

class Silnik
{
protected:
    double moc;
    double wymiary;
public:
    Silnik();
    Silnik( double, double );
    Silnik( const Silnik & );
    virtual ~Silnik();
    double get_moc();
    void set_moc( double );
    double get_wymiary();
    void set_wymiary( double );
    virtual void wypisz();
    Silnik * nast;
    void dodaj( Silnik * );
    void wypiszWiekszyNiz( double ); //poziom2
    void wypiszListe();
    virtual Silnik & operator +=( const Silnik & );
    virtual Silnik & operator =( const Silnik & );
};

class Elektryczny
    : public Silnik
{
protected:
    double napiecie;
    double bateria;
public:
    Elektryczny();
    Elektryczny( double, double, double, double );
    Elektryczny( const Elektryczny & );
    Elektryczny( const Silnik & );
    ~Elektryczny();
    double get_napiecie();
    void set_napiecie( double );
    double get_bateria();
    void set_bateria( double );
    void wypisz();
    Elektryczny & operator +=( const Elektryczny & );
    Elektryczny & operator =( const Elektryczny & );
};



Silnik::Silnik()
    : moc( 6 )
     , wymiary( 0 )
     , nast( nullptr )
{ }

Silnik::Silnik( double a_moc, double a_wymiary )
    : moc( a_moc )
     , wymiary( a_wymiary )
     , nast( nullptr )
{ }

Silnik::Silnik( const Silnik & obiekt )
    : moc( obiekt.moc )
     , wymiary( obiekt.wymiary )
{
    if( obiekt.nast )
         nast = new Silnik( * obiekt.nast );
    else
         nast = nullptr;
   
}

Silnik::~Silnik()
{
    if( nast )
         delete nast;
    //cout << "Usuniety silnik" << endl;
}

double Silnik::get_moc()
{
    return moc;
}

void Silnik::set_moc( double s_moc )
{
    moc = s_moc;
}

double Silnik::get_wymiary()
{
    return wymiary;
}

void Silnik::set_wymiary( double s_wymiary )
{
    wymiary = s_wymiary;
}

void Silnik::wypiszListe() //poziom2
{
    wypisz();
    if( nast )
         nast->wypiszListe();
   
}

void Silnik::wypisz()
{
    cout << "Silnik" << endl;
    cout << "Moc silnika: " << moc << endl;
    cout << "Wymiary silnika: " << wymiary << endl;
}

void Silnik::dodaj( Silnik * nowy )
{
    if( nast == nullptr )
         nast = nowy;
    else
         nast->dodaj( nowy );
   
}

void Silnik::wypiszWiekszyNiz( double liczba ) //poziom2
{
    if( moc > liczba )
         wypisz();
   
    if( nast )
         nast->wypiszWiekszyNiz( liczba );
   
}

Silnik & Silnik::operator +=( const Silnik & obiekt )
{
    moc += obiekt.moc;
    wymiary += obiekt.wymiary;
    return * this;
}

Silnik & Silnik::operator =( const Silnik & obiekt )
{
    if( this != & obiekt )
    {
        moc = obiekt.moc;
        wymiary = obiekt.wymiary;
    }
    return * this;
}

Elektryczny::Elektryczny()
    : Silnik()
     , napiecie( 0 )
     , bateria( 0 )
{ }

Elektryczny::Elektryczny( double a_napiecie, double a_bateria, double a_moc, double a_wymiary )
    : Silnik( a_moc, a_wymiary )
     , napiecie( a_napiecie )
     , bateria( a_bateria )
{ }

Elektryczny::Elektryczny( const Elektryczny & obiekt )
    : Silnik( obiekt.moc, obiekt.wymiary )
     , napiecie( obiekt.napiecie )
     , bateria( obiekt.bateria )
{
    if( obiekt.nast )
         nast = new Elektryczny( * obiekt.nast );
   
}

Elektryczny::Elektryczny( const Silnik & obiekt )
    : Silnik( obiekt )
{ }

Elektryczny::~Elektryczny()
{
    if( nast )
         delete nast;
    //cout << "Usuniety elektryczny" << endl;
}

double Elektryczny::get_napiecie()
{
    return napiecie;
}

void Elektryczny::set_napiecie( double s_napiecie )
{
    napiecie = s_napiecie;
}

double Elektryczny::get_bateria()
{
    return wymiary;
}

void Elektryczny::set_bateria( double s_bateria )
{
    bateria = s_bateria;
}

void Elektryczny::wypisz()
{
    cout << "Elektryczny" << endl;
    cout << "Moc silnika: " << moc << endl;
    cout << "Wymiary silnika: " << wymiary << endl;
    cout << "Napiecie: " << napiecie << endl;
    cout << "Czas pracy baterii: " << bateria << endl;
}

Elektryczny & Elektryczny::operator +=( const Elektryczny & obiekt )
{
    moc += obiekt.moc;
    wymiary += obiekt.wymiary;
    napiecie += obiekt.napiecie;
    bateria += obiekt.bateria;
    return * this;
}

Elektryczny & Elektryczny::operator =( const Elektryczny & obiekt )
{
    if( this != & obiekt )
    {
        moc = obiekt.moc;
        wymiary = obiekt.wymiary;
        napiecie = obiekt.napiecie;
        bateria = obiekt.bateria;
    }
    return * this;
}

template < class typ >
typ sumuj( typ * head )
{
    typ * temp = head;
   
    typ wynik = * head;
   
    while( temp->nast )
    {
        temp = dynamic_cast < typ *>( temp->nast );
        wynik += * temp;
    }
    //wynik.wypisz();
    return wynik;
}

int main()
{
    Elektryczny * head = new Elektryczny( 1, 2, 13, 26 );
    head->dodaj( new Elektryczny( 12, 28, 1, 35 ) );
    head->dodaj( new Elektryczny( 1, 100, 235, 35 ) );
    head->dodaj( new Elektryczny( 100, 200, 13, 356 ) );
   
    head->wypiszListe();
   
    cout << endl << "suma:" << endl;
    Elektryczny suma = sumuj( head );
    suma.wypisz();
   
    delete head;
    return 0;
}

Chodzi konkretnie o instrukcję "Elektryczny suma = sumuj(head)". Okazuje się, że w visualu funkcja albo niepoprawnie zwraca obiekt, albo w ogóle go nie zwraca. Sprawdzałem i sama funkcja szablonowa działa dobrze (można sprawdzić wpisując "wynik.wypisz()" przed return), jednak po wyjściu z funkcji komenda "suma.wypisz()" nic nie robi - tak jakby nie miała czego wypisać. Gdzie leży różnica w interpretacji kodu przez GNU i przez Visual?
P-171350
pekfos
» 2018-06-03 14:36:56
Wywal destruktor klasy Elektryczny.
P-171352
MeehoweCK
Temat założony przez niniejszego użytkownika
» 2018-06-03 14:54:56
Wielkie dzięki @pekfos. Czy możesz mi krótko wyjaśnić dlaczego ten destruktor wywoływał się jeszcze przed zwróceniem wyniku? I co gdyby w innej części kodu ten destruktor jednak był potrzebny? Destruktor klasy pochodnej nie jest wymagany do zwolnienia pamięci?
P-171354
pekfos
» 2018-06-03 15:06:59
Klasa Elektryczny nie potrzebuje destruktora do niczego. Ten który napisałeś był błędny. Pamięć zostanie zwolniona przez destruktor klasy bazowej. Zwalniając to w klasie pochodnej powodowałeś zwolnienie 2 razy, wkraczałeś w kompetencje klasy bazowej i w gruncie rzeczy napisałeś kod bez sensu i sprzeczny z założeniami programowania obiektowego.
P-171355
« 1 »
  Strona 1 z 1