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

[C++] Wskaźnik na destruktor

Ostatnio zmodyfikowano 2017-07-02 11:45
Autor Wiadomość
CPnHorror
Temat założony przez niniejszego użytkownika
[C++] Wskaźnik na destruktor
» 2017-07-02 06:11:02
Witam przy pomocy wskaźników (tablicy wskaźników) utworzyłem obiekty "wrogowie", jest ich 10.
Problem mój polega na wywołaniu destruktora (obiektów) nie usuwaniu wskaźników gdyż ilość wrogów jest ustalona z góry jako 10 co by ukrócić kod programu.
próbowałem :

C/C++
void zniszcz_wrogow()
{
   
    for( int zkz = 0; zkz < 10; zkz++ )
    {
        wsk[ zkz ] = delete wrog(); //    na zasadzie tworzenia " sks[zkz]=new wrog();  "
       
    }
   
}

a także:
C/C++
void zniszcz_wrogow()
{
   
    for( int zkz = 0; zkz < 10; zkz++ )
    {
        wsk[ zkz ]->delete wrog(); //  jak to inne funkcje uzywalem np. " wsk[zkz]->wrog::ruch; "
       
    }
   
}

i również:
C/C++
void zniszcz_wrogow()
{
   
    for( int zkz = 0; zkz < 10; zkz++ )
    {
        wsk[ zkz ]->wrog::~wrog(); // nawet w niechhlujny sposób jak ten
       
    }
   
}

FUNKCJA tworzenia 10-ciu obiektów "wrog" wygląda następująco:
C/C++
void losuj_wrogow()
{
    int yyyy, xxxx;
    bool czy_zyje;
    string mmoomm;
   
    bool warunek_o;
   
    for( int zkz = 0; zkz < 10; zkz++ )
    {
        warunek_o = false;
        do
        {
           
            xxxx =( rand() % 77 ) + 0;
            yyyy =( rand() % 22 ) + 0;
            mmoomm = map[ xxxx ][ yyyy ];
           
            if( mmoomm[ mmoomm.length() - 1 ] != '0' && wartosc_koloru_pola( map[ xxxx ][ yyyy ] ) != bezpieczny_kolor ) { warunek_o = true; }
        } while( warunek_o != true );
       
       
        if( zkz < ile_wrogow ) { czy_zyje = 1; } else { czy_zyje = 0; }
        wsk[ zkz ] = new wrog( xxxx, yyyy, czy_zyje );
       
    }
   
}

być może " nie rozumiem " w pełni tego co zrobiłem ale przy tworzeniu stworzyłem tablicę wskaźników (wsk) na obiekty które zaś przetwarzam przy pomocy pętli (oczywista oczywistość), po przejściu z mapki na kolejną mapkę usuwam obiekty i chcę zmienić wartości tablicy wskaźników na nowe obiekty itd itd.

wydaje mi się, że tylko źle wywołuję destruktor. naprostujcie mnie proszę o góru c++ :-)
P-162976
carlosmay
» 2017-07-02 10:13:49
C/C++
#include <iostream>

class Foo
{
public:
    Foo() { }
    ~Foo() { }
    void Method() { std::cout << "Method()\n"; }
};

int main()
{
    Foo * fptr = new Foo();
    fptr->Method();
    delete fptr; // zwalniasz pamięć, na którą wskazuje fptr, a nie wskaźnik
    fptr = nullptr; // teraz wskażnik jest pusty i możesz go ustawiać na inny obiekt typu Foo
}
Zainteresuj się:
» standard C++vector
inteligentnymi wskaźnikami
P-162977
Kinexity
» 2017-07-02 10:22:20
Muszę przyznać - dużo w tym fantazji, ale pozwól, że pomogę. Delete nie używamy, jak new - w sensie konstrukcja
wskaznik = delete[ typ ]()
 jest bez sensu. Komputer nie musi znać typu usuwanej zmiennej, ponieważ on po prostu (z tego co mi wiadomo) oznacza daną część pamięci jako wolną - wystarczy, że wie ile ma zwolnić, a nie musi wiedzieć co ma zwolnić. Zgodnie z moim doświadczenie destruktor można wywołać po prostu tak
wskaznik->~[ typ ]()
 i to powinno zadziałać.

+Taka mała porada - w warunku pętli zamiast
warunek_o != true
, lepiej wstawić
!warunek_o
 (lepiej wygląda i łatwiej się czyta ;D ).
P-162978
jankowalski25
» 2017-07-02 10:31:39
Jak już carlosmay wcześniej napisał, przecież wystarczy:
C/C++
delete wskaznik;
wskaznik = nullptr;
A jak masz tablicę, to zamiast
wskaznik
 wstawiasz
tablica[ indeks ]
.

Zgodnie z moim doświadczenie destruktor można wywołać po prostu tak
wskaznik->~[ typ ]()
 i to powinno zadziałać.
Z jakiego powodu chcesz ręcznie wywoływać destruktor? Używasz placement new? I po co te nawiasy kwadratowe przy typie?
P-162979
CPnHorror
Temat założony przez niniejszego użytkownika
» 2017-07-02 10:35:11
przepraszam uprzejmie, problem był nad wyraz głupi, po zaparzeniu kawy oraz wybudzeniu neuronów począłem myśleć a problem był następujący.

destruktor (złe):
C/C++
~wrog();

destruktor (poprawne):
C/C++
~wrog() { }

to ten średnik namieszał, bez średnika wszystko działa.
pewnie kompilator dzięki średnikowi uznał destruktor za osobną klasę...

dziękuję wszystkim za odpowiedź :-)
P-162980
jankowalski25
» 2017-07-02 10:40:49
pewnie kompilator dzięki średnikowi uznał destruktor za osobną klasę...
Prędzej linker stwierdził, że destruktor jest niezdefiniowany. Niemniej jednak bez konkretnego logu kompilacji nie można tego stwierdzić na pewno.

W każdym razie lepiej nie wywoływać ręcznie destruktora, jeśli nie ma takiej potrzeby. Jak już zostało napisane wcześniej, najprościej wywołać
delete
 na wskaźniku, a następnie przypisać mu wartość
nullptr
.
P-162981
Kinexity
» 2017-07-02 11:06:57
@jankowalski25
- nawiasy kwadratowe wstawiłem bo tak uznałem, że będzie lepiej (chociaż w rzeczywistości ich nie używam, żeby nie było)
- napisałem o ręcznym wywołaniu destruktora, ponieważ z tego co autor tematu na początku napisał zrozumiałem, że właśnie tego dotyczy problem (chociaż sam temat na to nie wskazuje)
P-162982
carlosmay
» 2017-07-02 11:22:23
Przykład z użyciem std::vector
C/C++
#include <iostream>
#include <vector>
#include <string>

class Enemy
{
public:
    Enemy( std::string const & en )
        : enemyName
    { en } { }
    ~Enemy() { }
    void Method() { std::cout << "Method()\n"; }
    std::string const & GetEnemmy() const { return enemyName; }
private:
    std::string enemyName;
};

using Enemies = std::vector < Enemy >;

void AppendEnemy( Enemies & e )
{
    // ustawienie argumentów
    std::string enemyName;
    std::getline( std::cin, enemyName );
    e.push_back( Enemy( enemyName ) );
}

Enemies::iterator RemoveEnemy( Enemies & e, Enemies::iterator it )
{
    return it = e.erase( it );
}

void ShowEnemies( Enemies const & e )
{
    for( auto const & el: e )
    {
        std::cout << el.GetEnemmy() << '\n';
    }
}

int main()
{
    Enemies enemies;
    AppendEnemy( enemies );
    AppendEnemy( enemies );
    AppendEnemy( enemies );
    ShowEnemies( enemies );
    auto it = enemies.begin() + 2;
    it = RemoveEnemy( enemies, it );
    ShowEnemies( enemies );
}

first enemy
second enemy
third enemy
first enemy
second enemy
third enemy
first enemy
second enemy
Nie opakowywałem tablicy wrogów w klasę zarządzającą dodawaniem i usuwaniem wrogów.
Zadanie pozostawiam tobie :]

napisałem o ręcznym wywołaniu destruktora
Najlepiej tego unikać. Wywołanie destruktora zwykle jest wywoływane w chwili opuszczenia scopu, w którym urzęduje obiekt
i może to powodować dwukrotne wywołanie destruktora dla jednego obiektu (błąd).
P-162983
« 1 » 2
  Strona 1 z 2 Następna strona