C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Статические функции и члены, Unresolve external
Benish
Отправлено: 01.03.2005, 18:05


Дежурный стрелочник

Группа: Участник
Сообщений: 67



Сделал classes.h в котором:

CODE

class Value                                        
   {
.......
       static Graphics::TBitmap VImage[2];
    public:
.......
       static void Set_image(AnsiString open, AnsiString close);
.......
   }
.......
void Value::Set_image(AnsiString open, AnsiString close)  
   {                              
       VImage[OFF].LoadFromResourceName((int)HInstance, close);
       VImage[ON].LoadFromResourceName((int)HInstance, open);
   }



В программе пишу:

CODE

void __fastcall TForm2::FormCreate(TObject *Sender)
{
......
    Value::Set_image("VAL_OP","VAL");
......
}


А при линковании все равно получаю:

CODE

[Linker Error] Unresolved external 'Value::VImage' referenced from MAIN.OBJ


Что я делаю не так?
Bond
Отправлено: 01.03.2005, 18:43


Станционный диспетчер

Группа: Участник
Сообщений: 142



В cpp-файле, в котором реализовываешь класс Value добавь строку:
CODE
Graphics::TBitmap Value::VImage[2];


Статические поля должны объявляться таким же макаром, как и методы
Benish
Отправлено: 02.03.2005, 12:20


Дежурный стрелочник

Группа: Участник
Сообщений: 67



дык в main.cpp есть:

CODE

#include "classes.h"



разве этого не достаточно?

Вписал руками:
/
CODE

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "main.h"
#include "classes.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;

TCanvas Value::*VCanvas;          



Компилируется и линкуется, но падает с access violation по записи.
Странно вообщем, буду разбираться.
Bond
Отправлено: 02.03.2005, 12:30


Станционный диспетчер

Группа: Участник
Сообщений: 142



Объявление класса не резервирует памяти под него. Память под класс выделяется при объявлении экземпляра класса.
Статические поля необходимо объявлять как и методы (см. литературу по C++)
Guest
Отправлено: 02.03.2005, 14:16


Не зарегистрирован







Спасибо!
Со второго раза дошло wink.gif Буду разбираться.
Benish
Отправлено: 03.03.2005, 13:24


Дежурный стрелочник

Группа: Участник
Сообщений: 67



Ничего не получается!
Приведу еще раз код.
.h:
CODE

enum {OFF,ON};
class Value
{
       static Graphics::TBitmap VBitmap[2];
//        static Graphics::TCanvas *VCanvas;
       int X,Y;
       bool Pos;
   public:
       Value(int cx=0, int cy=0, bool cpos=OFF);
       void Set(bool cpos);
       static void Set_VBitmap(const AnsiString &open, const AnsiString &close);
//        static void Set_VCanvas(TCanvas *ccanvas);
   private:
};



Теперь .срр:

CODE

#include "Unit1.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Graphics::TBitmap Value::VBitmap[2];
//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
//    Value::Set_VCanvas(Image1->Canvas);
   Value::Set_VBitmap("KL_OP","KL");
   Value *vl = new Value(15,25,ON);
   delete vl;
}
//---------------------------------------------------------------------------

Value::Value(int cx, int cy, bool cpos)
{
   X = cx;
   Y = cy;
   Pos = cpos;
}
//---------------------------------------------------------------------------

void Value::Set(bool cpos)
{
   Pos = cpos;
}
//---------------------------------------------------------------------------

void Value::Set_VBitmap(const AnsiString &open, const AnsiString &close)
{
//     Value::VBitmap[OFF] = new Graphics::TBitmap();
    Value::VBitmap[OFF].LoadFromResourceName((int)HInstance, close);
//     Value::VBitmap[ON] = new Graphics::TBitmap();
    Value::VBitmap[ON].LoadFromResourceName((int)HInstance, open);
}
//---------------------------------------------------------------------------



В таком варианте все запускается и падает с access violaiton.
Если изменить VBitmap[2] на *VBitmap[2] то при линковании получаем Unresolved.
Bond
Отправлено: 03.03.2005, 14:46


Станционный диспетчер

Группа: Участник
Сообщений: 142



А Вы читали справку по конструктору класса TBitmap?
QUOTE
Description

Call TBitmap indirectly, using the new keyword, to instantiate a bitmap object at runtime.
Bond
Отправлено: 03.03.2005, 14:58


Станционный диспетчер

Группа: Участник
Сообщений: 142



Это вставь в *.cpp
CODE
Graphics::TBitmap *Value::VBitmap[2] = { new Graphics::TBitmap, new Graphics::TBitmap };

Это — в *.h
CODE
static Graphics::TBitmap *VBitmap[2];

И замени обращения
QUOTE
value::VBitmap[OFF].LoadFromResourceName((int)HInstance, close);
Value::VBitmap[ON].LoadFromResourceName((int)HInstance, open);
на
CODE
Value::VBitmap[OFF]->LoadFromResourceName((int)HInstance, close);
Value::VBitmap[ON]->LoadFromResourceName((int)HInstance, open);
GIZMO
Отправлено: 04.03.2005, 10:30


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (Benish @ 01/03/2005, 18:05)
Сделал classes.h в котором:

CODE

class Value
{
.......
static Graphics::TBitmap VImage[2];
public:
.......
static void Set_image(AnsiString open, AnsiString close);
.......
}
.......
void Value::Set_image(AnsiString open, AnsiString close)
{
VImage[OFF].LoadFromResourceName((int)HInstance, close);
VImage[ON].LoadFromResourceName((int)HInstance, open);
}



В программе пишу:

CODE

void __fastcall TForm2::FormCreate(TObject *Sender)
{
......
Value::Set_image("VAL_OP","VAL");
......
}


А при линковании все равно получаю:

CODE

[Linker Error] Unresolved external 'Value::VImage' referenced from MAIN.OBJ


Что я делаю не так?

Статические члены надо инициализировать вне класса
CODE

//in hpp
class Value                                        
   {
.......
       static Graphics::TBitmap *VImage[2];
    public:
.......
       static void Set_image(AnsiString open, AnsiString close);
.......
   }
.......
//сpp
Graphics::TBitmap Value::VImage[0] = new Graphics::TBitmap();
Graphics::TBitmap Value::VImage[1] = new Graphics::TBitmap();

так вроде?
Bond
Отправлено: 04.03.2005, 11:34


Станционный диспетчер

Группа: Участник
Сообщений: 142



Смотри выше. Не верно, потому что ты этим
QUOTE
Graphics::TBitmap Value::VImage[0] = new Graphics::TBitmap();
Graphics::TBitmap Value::VImage[1] = new Graphics::TBitmap();
объявляешь два поля класса Value:
1-ое — массив с 0 елементов Graphics::TBitmap*
2-ое — массив с 1 элемента Graphics::TBitmap*
А нужно объявить массив с двух элементов Graphics::TBitmap*, который пристутствует в классе.
Смотри:
QUOTE
Это вставь в *.cpp
CODE
Graphics::TBitmap *Value::VBitmap[2] = { new Graphics::TBitmap, new Graphics::TBitmap };


Это — в *.h
CODE
static Graphics::TBitmap *VBitmap[2];

GIZMO
Отправлено: 04.03.2005, 12:29


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (Bond @ 04/03/2005, 11:34)
Это вставь в *.cpp
CODE
Graphics::TBitmap *Value::VBitmap[2] = { new Graphics::TBitmap, new Graphics::TBitmap };


Это — в *.h
CODE
static Graphics::TBitmap *VBitmap[2];

[/QUOTE]

Да. Поторопился.
Benish
Отправлено: 04.03.2005, 18:26


Дежурный стрелочник

Группа: Участник
Сообщений: 67



Большое спасибо Bond'y, разобрался. Все работает.



Вернуться в Вопросы программирования в C++Builder