Przekazywanie obiektu i tablicy obiektów do funkcji

0

Witam
Piszę pewien testowy program i natrafiłem na problem z wykorzystywaniem zarówno tablicy obiektów jak i pojedynczego obiektu jako argumentu napisanej przeze mnie funkcji. Sprawy mają się tak:
Przycisk 1 tworzy tablicę przycisków i nadaje im odpowiednie położenie, zaś **przycisk 2 **ma za zadanie przesuwać te utworzone przyciski. Po naciśnięciu przycisku 2 wywołuje się funkcja przesuwanie,która powinna zmieniać atrybut Left każdego z przycisków (na które wskazuje tablica) o określoną wartość, oraz zmieniać atrybut Caption na przycisku 2.
Program się kompiluje, w trakcie działania również nie generuje żadnych błędów, jednak po naciśnięciu przycisku 2 nic się nie dzieje...
Oto kod źródłowy:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

bool x=true;

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (x)
{
        TButton * btn [5];
        for (int i=0; i<5;i++)
                {
                btn[i]= new TButton(this);
                btn[i]->Parent = this;
                }
        for (int i=0; i<5;i++)
         {
                btn[i]->Top=50+i*100;
         }
        x=false;
}
else
        Form1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        void __fastcall przesuwanie(TButton *btn[],TButton &Button2);
}
//---------------------------------------------------------------------------
void __fastcall przesuwanie(TButton *btn[],TButton &Button2)
{
        for (int i=0; i<5;i++)
            {
            btn[i]->Left+=20;
            }
        Button2.Caption="dziala";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
        delete [] btn;
}
//---------------------------------------------------------------------------
Oraz kod nagłówkowy:
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TButton *Button1;
        TButton *Button2;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
        void __fastcall Button2Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
TButton*btn[];

      __fastcall TForm1(TComponent* Owner);
      void __fastcall przesuwanie(TButton *btn[],TButton &Button2);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Co zrobić, aby przycisk 2 spełniał swoją funkcję jak należy? Proszę o pomoc i z góry dzięki. :)

0
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    void __fastcall przesuwanie(TButton *btn[],TButton &Button2);
}

Wewnątrz funkcji Button2Click zamiast wywołać funkcję przesuwanie to deklarujesz ponownie funkcję o nazwie przesuwanie. Zmień na:

przesuwanie(btn, Button2);   // możliwe, że z __fastcall (nie znam Borlanda)

Swoją drogą to trochę fail C++, że pozwala na takie rzeczy.

0
TButton * btn [5];

Tutaj deklarujesz zmienną lokalną, która przysłania cokolwiek masz wyżej o tej nazwie.

0

I jeszcze ja powiem tak trochę nie w temacie, że źle robisz definiując zmienną

bool x=true;

jako globalną. Zrób z niej składową TForm1

0
twonek napisał(a):
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    void __fastcall przesuwanie(TButton *btn[],TButton &Button2);
}

Wewnątrz funkcji Button2Click zamiast wywołać funkcję przesuwanie to deklarujesz ponownie funkcję o nazwie przesuwanie. Zmień na:

przesuwanie(btn, Button2);   // możliwe, że z __fastcall (nie znam Borlanda)

Swoją drogą to trochę fail C++, że pozwala na takie rzeczy.

Niestety, przy próbie takiego wywołania funkcji pojawia się błąd *[C++ Error] Unit1.cpp(44): E2451 Undefined symbol 'btn'*, bez względu na __fastcall.
Patryk27 napisał(a):
TButton * btn [5];

Tutaj deklarujesz zmienną lokalną, która przysłania cokolwiek masz wyżej o tej nazwie.

Faktycznie, ta deklaracja przeszkadza, szczególnie że tablicę btn[] mam zadeklarowaną w pliku nagłówkowym. Jednak gdy usuwam tę deklarację z funkcji OnClick przycisku 1, to przy wywoływaniu procesu delete w funkcji OnClose, wyskakuje mi błąd *Access Violation*.

Co do deklarowania zmiennej x, to już wszystko poprawiłem, jest zadeklarowana w pliku nagłówkowym, a wartość przypisuje jej funkcja OnCreate, dzięki za uwagę :)
0

Wrzuć aktualny kod.

1
Zikos napisał(a):
twonek napisał(a):
przesuwanie(btn, Button2);   // możliwe, że z __fastcall (nie znam Borlanda)

Niestety, przy próbie takiego wywołania funkcji pojawia się błąd [C++ Error] Unit1.cpp(44): E2451 Undefined symbol 'btn', bez względu na __fastcall.

Bo:

TButton*btn[];

niepoprawna deklaracja, trzeba podać rozmiar tablicy,

TButton * btn [5];

przesłanianie powyższej tablicy,

delete [] btn;

niepoprawne usuwanie, delete musi być symetryczne z new, więc jeżeli było

for (...) btn[i] = new...

to ma być

for (...) delete btn[i];

Zauważ, że nigdzie nie użyłeś new[], więc na pewno nie wolno użyć delete[].

0

Mimo zmienienia argumentów funkcji przesuwanie na (btn,Button2), oraz zadeklarowania tablicy wraz z rozmiarem, kompilator nadal generuje ten sam błąd E2451 Undefined symbol 'btn'.
Dzięki za pomoc w kasowaniu obiektów, ten sposób użycia delete jest faktycznie bardziej sensowny.

Oto aktualny kod źródłowy:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"



TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (x)
{

        for (int i=0; i<5;i++)
                {
                btn[i]= new TButton(this);
                btn[i]->Parent = this;
                }
        for (int i=0; i<5;i++)
         {
                btn[i]->Top=50+i*100;
         }
        x=false;
}
else
        Form1->Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        void __fastcall przesuwanie(btn,Button2);
}
//---------------------------------------------------------------------------
void __fastcall przesuwanie(TButton *btn[],TButton &Button2)
{
        for (int i=0; i<5;i++)
            {
            btn[i]->Left+=20;
            }
        Button2.Caption="dziala";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
for(int i =0; i<=5;i++)
        delete  btn[i];
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
x=true;
}
//---------------------------------------------------------------------------

Oraz kod nagłówkowy:

/---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TButton *Button1;
        TButton *Button2;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
        void __fastcall Button2Click(TObject *Sender);
        void __fastcall FormCreate(TObject *Sender);
private:	// User declarations
public:		// User declarations
TButton*btn[5];
bool x;

      __fastcall TForm1(TComponent* Owner);
      void __fastcall przesuwanie(TButton *btn[],TButton &Button2);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
0

1.Popraw formatowanie kodu.
2.Nie rozumiem, dlaczego robisz sobie tablicę wskaźników na obiekty zamiast tablicę obiektów.
3.Zadeklarowałeś przesuwanie jako metodę klasy TForm1, lecz nie zdefiniowałeś jej w taki sposób.

0

I jeszcze trzeba dodać powód AV podczas zamykania okna:

  for(int i =0; i<=5;i++)
    delete btn[i];

Tablica jest 5 elementowa, a Ty usuwasz 6 elementów.

@Patryk27 najbardziej eleganckim rozwiązaniem jak dla mnie, to nie byłoby użycie tablicy, ale jakiegoś kontenera. VCL udostępnia ich parę i są nawet dedykowane co trzymania listy komponentów TComponentList.

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