Помогите ламеру с классами
{
public:
void SetCreated(void) { Created = 1; }
private:
int Created;
};
подскажите плиз как в проге потом вызвать данную ф-цию?Пробовал
Project *a;
a.SetCreated();
и
a->SetCreated();
оба варианта неверны...
Подскажите пожалуйста что я не правильно делаю и как правильно?
Заранее спасибо!
Второй не верен, видимо потому что это указатель. А раз указатель, прежде чем обращаться к обеъекту - надо его сначала создать и передать его адресс в указатель.
Тоесть или так:
a.SetCreated();
или так:
a->SetCreated();
или так:
Project *a = &b;
a->SetCreated();
=))
Пишет Multiple declaration for 'a'
А если набирать, то после "->" пишет
[COLOR="DarkRed"][C++ Error] Unit1.cpp(1): Unable to invoke Code Completion due to errors in source code[/COLOR]
Если можно напиши плиз простенький примерчик класса и выхова его ф-ций для Б6...
//Class.h
{
private:
int iVar; // переменная доступная только из методов класса
void fFunc(); // метод доступный только из других методов класса
public:
int iVar2; // переменная доступная везде
TClass(); // конструктор
void pubFunc(int); // метод доступный для вызова отовсюду
~TClass(); // деструктор
};
//Class.cpp
//-------------------------------------------------------------------------
TClass::TClass() // конструктор. Вызывается автоматически при создании экземпляра объекта класса. Можно использовать для инициализации переменных. Как и в функцию можно добавить параметры.
{
}
//-------------------------------------------------------------------------
TClass::~TClass() // деструктор. Вызывается автоматически при уничтожении экземпляра объекта класса. Тут можно освободить области памяти, которые не освобождаются автоматичеси, выгрузить какие-то данные.
{
}
//-------------------------------------------------------------------------
int TClass::fFunc()
{
return iVar2 * 2;
}
//-------------------------------------------------------------------------
int TClass::pubFunc(int i)
{
iVar2 = i;
return fFunc();
}
//Unit1.cpp
a.pubFunc(1); // вызываем публичный метод
Еще вот такой вопросик, я хочу в классе использовать переменную типа TADOConnection, подскажите плиз как ее обьявить и как инициализировать?
Тебе надо завести приватный указатель на экземпляр объекта класса TADOConnection. Создавать экземпляр объекта можно либо в конструкторе твоего класса либо в публичном методе, написать, что-то типа метода Initialize();. В деструкторе можно прописать удаление экземпляра объекта класса. Если хочешь написать просто wrapper для ADO компонентов, то можно унаследовать класс.
Тебе надо завести приватный указатель на экземпляр объекта класса TADOConnection. Создавать экземпляр объекта можно либо в конструкторе твоего класса либо в публичном методе, написать, что-то типа метода Initialize();. В деструкторе можно прописать удаление экземпляра объекта класса. Если хочешь написать просто wrapper для ADO компонентов, то можно унаследовать класс.[/QUOTE]
Ну, как бы это выразится...а можно примерчик?Ато я что-то мало чего понял... :)
З.Ы: ну просто очень очень нужно!Буду весьма признателен за простенький, доступный моему уму примерчик :)
З.З.Ы: когда пишу в привате в классе:
TADOConnection *AC1;
а в конструкторе класса:
AC1 = new TADOConnection();
пишет
[COLOR="DarkRed"][C++ Error] Classes.cpp(43): E2285 Could not find a match for 'TADOConnection::TADOConnection()'[/COLOR]
З.Ы: ну просто очень очень нужно!Буду весьма признателен за простенький, доступный моему уму примерчик
Пожалуйста
в .h файле
#include <ADODB.hpp>
#include <DB.hpp>
// ...............
class TcDB_Interface
{
private:[INDENT]
TADOConnection *_fConnection; // Закрытое поле - указатель на объект
[/INDENT]
public:[INDENT]
__property TADOConnection *Connection = {read = _fConnection}; // Публичное свойство для обращения к объекту - указатель на объект
__fastcall TcDB_Interface (void); // Конструктор объекта
__fastcall ~TcDB_Interface (void); // Деструктор объекта
[/INDENT]};
в .cpp файле
{
_fConnection = new TADOConnection (NULL); // Создание вложенного объекта и связывание с полем-указателем
}
__fastcall TcDB_Interface ::~TcDB_Interface (void)
{
delete _fConnection; // Удаление вложенного объекта по его укзателю
}
Пойдёт пример.
А самое главное в C++ - это понять, что такое "указатель" и как выделять/удалять объекты из памяти с использованием этих указателей. Без понимания этого, дальше "Hello world" не продвинешься ;)
Каак это поправиьт? :(
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ADODB.hpp>
#include <DB.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *btn1;
TADOConnection *con1;
void __fastcall btn1Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
class TmClass
{
private:
public:
TADOConnection *padoCon;
TmClass();
~TmClass();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//unit1.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TmClass *tc=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
tc = new TmClass;
}
//---------------------------------------------------------------------------
TmClass::TmClass()
{
try{
padoCon = new TADOConnection(0);
}catch(...){
padoCon = NULL;
}
}
TmClass::~TmClass()
{
if (padoCon) delete padoCon;
}
void __fastcall TForm1::btn1Click(TObject *Sender)
{
tc->padoCon->ConnectionString = "FILE NAME=Server.udl";
tc->padoCon->Connected = true;
if(tc->padoCon->Connected){
ShowMessage("Соединились.");
}
}
//---------------------------------------------------------------------------
Можно ли создать ADOConnection непосредственно в самом классе?Т.е. не кидать на форму, а создать его в классе MyClass например ADOConnection1, а потом в программе сделать вот так:
MyClass *a = new MyClass();
a->ADOConnection1->ConnectionString = "bla bla bla";
a->ADOConnection1->Connected = true;
и т.д.
Если можно напишите плиз как?
Ты что тут изваял :confused: - сам чёрт ногу сломит :eek: .
Zeran же в жизни не разберётся в этом "монументализме" :(
Тем более, что есть два недочёта
1. "TADOConnection *con1" - в описании формы. Зачем, ведь мы создаём объект отдельно?. И где объявление tc?
2. Если в строке "padoCon = new TADOConnection(0);" произойдёт ошибка, то в методе TForm1::btn1Click получим мощный Access Violation :(
3. Так как тип TmClass содержит только одно поле - указатель, и не является производным от TOBject, то его объекты лучше реализовывать напрямую, без указателей. Соответственно, не будет нужды обрабатывать его в конструкторе/деструкторе, да и сама программа быстрее работать будет
{
// .......
private:
TmClass tc;
// .....
};
Zeran
Так что же у тебя выдаётся? Кстати, кто выдаёт: компилятор, линковщик или же сама программа в момент выполнения.
Но помому (если это возможно) луче сделать как в посте №12?
Ты что тут изваял :confused: - сам чёрт ногу сломит :eek: .
Zeran же в жизни не разберётся в этом "монументализме" :(
[/QUOTE]
Наоборот должно помочь. Так видно куда суется класс и где реализуются методы.
[QUOTE=el scorpio]
Тем более, что есть два недочёта
1. "TADOConnection *con1" - в описании формы. Зачем, ведь мы создаём объект отдельно?.
[/quote]
Подумаешь указатель лишний забыл удалить :), просто не хотелось хидеры вручную прописывать для ADOConnect.
[QUOTE=el scorpio]
И где объявление tc?
[/quote]
Посмотри внимательнее, там объявление указателя tc есть перед конструктором формы.
[QUOTE=el scorpio]
2. Если в строке "padoCon = new TADOConnection(0);" произойдёт ошибка, то в методе TForm1::btn1Click получим мощный Access Violation :
[/quote]
Получим конечно. Просто в один момент мне перехотелось писать Safe код. Принцип главное понятен.
[QUOTE=el scorpio](
3. Так как тип TmClass содержит только одно поле - указатель, и не является производным от TOBject, то его объекты лучше реализовывать напрямую, без указателей. Соответственно, не будет нужды обрабатывать его в конструкторе/деструкторе, да и сама программа быстрее работать будет
[/quote]
В этом случае будет всего один объект. Мало ли, человеку захочется сделать десяток соединений.
MyCmass *a = new MyClass();
и оно матюгалось, но когда сделал вот так:
MyClass *a=0;
А потом в __fastcall TForm1::TForm1:
a = new MyClass;
все начало работать гуд!
Большое всем спасибо!
З.Ы: коденет рулит!С меня море виртуального пифа :)
У меня проще и понятнее было :D .
Где, в упор не вижу....
А, нашёл - глобальный :eek: указатель на объект. Создаётся в конструкторе формы :eek:. Угадайте с трёх раз, что получиться, если где-нибудь в процессе выполнения программы создать ещё одну "форму1" :D . Правильно - утечку памяти - потеряем указатель на существующий объект. А после удаления второй формы - очередной AV при первом же обращении к объекту.
Zeran, запомни, как "Отче наш". Если какой-нибудь объект создаётся другим - то он должен быть полем своего родителя.
Глобальных указателей на объекты не плоди - только на формы. Всё остальное пусть будет полями форм, создаваться в конструкторах форм и удаляться в их же деструкторах.
Глобальными переменными не увлекайся. Если форма или другой большой объект активно используют значение - объявляй полем объекта. Если это должны использовать другие объекты - создавай свойство, позволяющее выполнять чтение/запись свойства.
Помни, грамотно спроектированная иерархия классов - половина решения задачи. Всё остальное само-собой разрешится.
Пусть люди принципы понимают, как положено, "с чувством, с толком, с расстановкой".
Это все понятно. Програмирование оно на то и программирование, чтобы дать волю своему воображению. А создание второго TForm1 это всего-лишь возможное условие постановки задачи. Но я за то, чтобы заранее делать все правильно, т.к. в будущем многое может поменяться.
[QUOTE=el scorpio]
Пусть люди принципы понимают, как положено, "с чувством, с толком, с расстановкой".[/QUOTE]
Если дальше двигаться в этом же направлении, то тема перетечет в целесообразность использования new/delete, смарт поинтеры, стандарты, стиль программирования...
Я типа создал Коннекшн в своем классе, а как теперь сделать для него обработчики событий, например АфтерКоннект и ОнДисконнект?
[COLOR="DarkRed"]Classes.cpp[/COLOR]
{
public:
Project();
~Project();
TADOConnection *Connection;
TADOCommand *Command;
TADODataSet *DataSet;
private:
};
[COLOR="DarkRed"]Classes.h[/COLOR]
{
Connection = new TADOConnection(NULL);
Command = new TADOCommand(NULL);
DataSet = new TADODataSet(NULL);
}
Project::~Project()
{
delete Connection;
delete Command;
delete DataSet;
}
Не объявляй поля классов как общие - для них нужно использовать private
Кстати, если требуется создать событие для своего объекта, можно использовать следующий код
{
private:
TNotifyEvent _fOnEvent; //Обработчик события
inline void Event (void)
{if (_fOnEvent) // Проверка наличия обработчика события
_fOnEvent (this);} // Вызов функции - обработчика события для этого объекта
public:
void Make_Somesing (params);
__property OnEvent = {read = _fOnEvent, write = _fOnEvent}; // Свойство чтения/записи обработчика события
}
void TMyClass::Make_Somesing (params)
{
//Метод объекта, делающий что-нибудь :)
// ......
this->Event(); // А здесь происходит событие объекта
// ......
}
Определение типа TNotifyEvent можно посмотреть в help'е или выбрав в контекстном меню редактора кода "Find definition".
Если требуется использовать событие другого типа (например, для объекта, наследуемого не от TObject), или передать в обработчик параметры события, можно определить свой тип события.
Тип "событие" выглядит как указатель на функцию, но имеет ключевое слово __closure.
Вот например мой класс:
[COLOR="DarkRed"]Classes.cpp[/COLOR]
{
public:
Project();
~Project();
TADOConnection *Connection;
TADOCommand *Command;
TADODataSet *DataSet;
private:
};
[COLOR="DarkRed"]Classes.h[/COLOR]
{
Connection = new TADOConnection(NULL);
Command = new TADOCommand(NULL);
DataSet = new TADODataSet(NULL);
}
Project::~Project()
{
delete Connection;
delete Command;
delete DataSet;
}
Как для Connection сделать обработчик AfterConnect?
{
TProject *MyObject = new TProject(); // Создаём требуемый объект
MyObject->Connection->OnAfterConnect = this->Connection_Event;
// ConnectionEvent (TObject *Sender) - это созданный метод класса TForm1
}
И ещё перемести указатели на объекты в private.
А то если сдуру сделаешь что-нибуть типа "MyObject->Connection = Другой_Объект", и будешь репу чесать: почему программа в Access Violation со свистом :) улетает :confused:.
Создаю в классе:
TStrings *Params;
в конструкторе:
Params = new TStrings;
а оно мне при компиле пишеть:
[COLOR="DarkRed"][C++ Error] Unit1.cpp(28): E2352 Cannot create instance of abstract class 'TStrings'[/COLOR]
[COLOR="DarkRed"][C++ Error] Unit1.cpp(28): E2353 Class 'TStrings' is abstract because of '_fastcall TStrings::Get(int) = 0'[/COLOR]
:(
Создаю в классе:
TStrings *Params;
в конструкторе:
Params = new TStrings;
а оно мне при компиле пишеть:
[COLOR="DarkRed"][C++ Error] Unit1.cpp(28): E2352 Cannot create instance of abstract class 'TStrings'[/COLOR]
[COLOR="DarkRed"][C++ Error] Unit1.cpp(28): E2353 Class 'TStrings' is abstract because of '_fastcall TStrings::Get(int) = 0'[/COLOR]
:([/QUOTE]
От данного класса можно наследовать, но объект данного класа создать нельзя. Потому как виртуальный он.
Если необходимо - или создавай свой или используй TStringsList.
Во блин заговорился - имелось ввиду абстрактный
Есть такое понятие, как виртуализация методов класса.
В двух словах - это когда в базовом классе один метод объекта хочет вызывать другой, но, сам того не подозревая, вызывает метод производного класса этого же объекта, потому что тот объявлен "виртуальным".
А бывает так, когда неизвестно, что этот метод должен делать в базовом классе - но без этого действия не обойтись. Тогда программист пишет, что реализация такого метода "равна нулю", а уже в производных классах описывает, что этот метод должен делать для конкретного объекта. Подобные методы называются "абстрактными", соответственно классы с этими методами тоже. Объекты абстрактных классов создавать нельзя, потому что они сами по себе не могут работать.
TStrings - абстрактный класс - он не имеет своего кода для выполнения чтения-записи строк. Все эти действия реализованы в классе TStringList.
Обычно используются указатели на TStringList: "TStringList *list = new TStringList();".
Если же по какой-то причине хочется использовать указатель на TStrings - пожалуйста: "TStrings *list = new TStringList();"