Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Вниз

Небольшой вопрос про наследование   Найти похожие ветки 

 
SkyRanger   (2003-10-31 16:21) [0]

У меня есть класс TOpenGL

TOpenGL = class
WinContent : hDC; //Контекст окна
GLContent : hGLRC; //Контекст OpenGL
GLFOV : GLFloat; //Значение FOV
MaxX, MaxY : Integer; //Максимальные значения X и Y (Разрешение экрана)
WinHeight : Integer; //Высота окна
WinWidth : Integer; //Ширина окна

///

public
procedure InitOpenGL(WinhDC : hDC; cBits,dBits : byte; fov : GLFloat; glWinHeidht, glWinLength : Integer);//Инициализирует OpenGl
procedure DestroyOpenGL;//Инициализирует OpenGl

procedure ResizeWindow(WinMaxWidth, WinMaxHeigh : Integer);//Сохраняет пропорции при изменении размера окна
procedure UpdateWindow; //Обновляет окно

private
procedure SetDCPixelFormat(mhdc : hDC;cBits,dBits : byte);//Устанавливает формат пикселей для устройства

end;

так же есть наследуемый от него класс TGLConsole

TGLConsole = class (TOpenGL)
MessageList:array [0..100] of String;
fnt:TGLFont;
ConsoleList:GLUInt;
ConsoleTex:TGLTExture;
Constructor Init(Msg:String);
Procedure DrawConsole;
Destructor Destroy;
end;

Наследование я сделал чтобы каждый раз не передавать через параметры контексты окна, размеры окна и контексты OpenGL это все гомерно получается и некраиво.
Теперь, по идее хотелось бы нписать что то типа
Console:=MyOpenGl.OpenGL;
Но косяк в том что по правилам енто невозможно так как присваивание возможно тока в направлении Родитель<-наследник
Подскажите плмз наиболее оптимальный метод решения. Т.е. Автоматического заполнения наследуемых полей у потомка из полей родителя...


 
Stratos   (2003-11-01 03:25) [1]

попробуй так:
допустим

var
Console: TGLConsole;
OpenGL: TOpenGL;
...
begin
(Console as TOpenGL):= OpenGL;
end;


 
SkyRanger   (2003-11-01 07:14) [2]

>Stratos © (01.11.03 03:25) [1]
Не катит! Выдает мол типы не совместимы и левая часть не может быть назначенна...
Почитал хелп, там написанно что так должно работать вот пример из хелпа:
type
TAncestor = class
Value: Integer;
end;
TDescendant = class(TAncestor)
Value: string; // hides the inherited Value field
end;
var
MyObject: TAncestor;
begin
MyObject := TDescendant.Create;
MyObject.Value := "Hello!"; // error
TDescendant(MyObject).Value := "Hello!"; // works!
end;

Я так подумал если написать так TOpenGL(Console).:=OpenGL;
то должно сработать... Ан нет... пришлось обломиться...
Есть еще предложения???
Вписывать в объявление класса экземпляр класса TOpenGl не хочется, так как приджется следить за выделением и освобождением памяти... А раз он наследуется в дочернем классе то почему бы не заполнить все поля автоматически, а не вводить в Init конструктор кучу присваиваний...


 
yo   (2003-11-01 09:15) [3]

Коирование в таком виде, в котором ты хочешь - это всего
лишь копирование указателей.
А тебе, насколько я понял, нужно именно скопировать данные из одного объекта в другой, что-то вроде

Console.Assign(OpenGL);


 
SkyRanger   (2003-11-01 11:23) [4]

Нефига! У меня класс не потомок TPersistent и не нада ентого!
Пытался встроить в свой класс методы из TPersistent нефига не вышло и тем более не понятно где тут он производит непосредственно присваивание. Создается ощющение что этот код кроме обработки ошибок больше нефига не делает!!!

procedure TPersistent.Assign(Source: TPersistent);
begin
if Source <> nil then Source.AssignTo(Self) else AssignError(nil);
end;

procedure TPersistent.AssignError(Source: TPersistent);
var
SourceName: string;
begin
if Source <> nil then
SourceName := Source.ClassName else
SourceName := "nil";
raise EConvertError.CreateResFmt(@SAssignError, [SourceName, ClassName]);
end;

procedure TPersistent.AssignTo(Dest: TPersistent);
begin
Dest.AssignError(Self);
end;


 
SkyRanger   (2003-11-01 11:27) [5]

Или же тут придется самомоу писать свой Assign??? Как у TFont???

procedure TFont.Assign(Source: TPersistent);
begin
if Source is TFont then
begin
Lock;
try
TFont(Source).Lock;
try
FontManager.AssignResource(Self, TFont(Source).FResource);
Color := TFont(Source).Color;
if PixelsPerInch <> TFont(Source).PixelsPerInch then
Size := TFont(Source).Size;
finally
TFont(Source).Unlock;
end;
finally
Unlock;
end;
Exit;
end;
inherited Assign(Source);
end;


 
Юрий Зотов   (2003-11-01 12:42) [6]

Так Вы что конкретно хотите сделать - присвоить ссылку или скопировать содержимое? Если первое, то никакой Assign Вам не нужен.

Вообще, вопрос непонятен. Давайте уберем все лишнее и сведем задачу к сути. Есть два класса:

TParent = class // прямой наследник TObject
...
end;

TChild = class(TParent)
...
end;

Теперь скажите - что конкретно требуется сделать?


 
SkyRanger   (2003-11-01 13:09) [7]

Нужно чтобы все поля принадлежащие классу TParent наследованные в классе TChild обновились автоматически... Т.е. я создаю класс
TParent затем класс TChild. При инициализации класса TParent его поля заполняются некоторой информацией, которую нужно без лишней мороки перенести в класс TChild т.к. она в нем неоднократно используется, и передавать каждому методу эти данные как параметр неэффективно!


 
Palladin   (2003-11-01 13:24) [8]

Создай record с нужными полями и работай с его экземплярами.
Это избавит тебя от кучи :=


 
Юрий Зотов   (2003-11-01 13:38) [9]

Надо просто создать экземпляр класса TChild и ничего никуда "переносить" не нужно. Он же наследник - а потому вся инициализация будет унаследована Нужно только грамотно написать классы, вот и все. Например:

type
TParent = class
protected
procedure Initialize; virtual;
public
constructor Create;
end;

TChild = class(TParent)
protected
procedure Initialize; override;
end;

constructor TParent.Create;
begin
inherited;
Initialize
end;

procedure TParent.Initialize;
begin
... // Все, что нужно инициализировать ТОЛЬКО в классе TParent
end;

procedure TChild.Initialize;
begin
inherited; // Инициализирутся унаследованные поля.
... // Собственная дополнительная инициализация
end;

Если в классе TChild собственная дополнительная инициализация не требуется, то и метод Initialize в нем не нужен - из конструктора вызовется унаследованный Initialize.


 
SkyRanger   (2003-11-01 13:54) [10]

А если этот клас инициализирует OpenGL и ДОЛЖЕ быть создан и вызван ТОЛЬКО 1 раз, но данные которые он получает в процессе работы необходимы в последующем???
Тут я имею ввиду не описания классов, а ЭКЗЕМПЛЯРЫ т.е. прошедшие
Parent:=TParent.Create;
Parent.Init(wnd,16,16,45, WinHeight,WinWidth);
Child:=TChild.Create;
Причем Parent:=TParent.Create;
Обязательно должен быть вызван первым и данные которые он получит в процессе своей работы, а также переданные ему wnd,16,16,45, WinHeight,WinWidth должны быть доступны в наследнике Child.
Может я что то не так понимаю, но мне нужно чтобы работало все так. Можно это сделать как нибудь???
То что вы предлагаете ведет к наследованию методов, т.е. кода, который должен выполняться ВСЕГО ОДИН РАЗ. причем наследников у этого класса будет очень много!
Такая вот непростая ситуация...


 
Юрий Зотов   (2003-11-01 15:27) [11]

interface

type
TParent = class
protected
procedure Initialize; virtual;
public
constructor Create;
destructor Destroy; overide;
end;

TChild = class(TParent)
protected
procedure Initialize; override;
procedure AssignCurrentProps;
end;

function GetPrimary: TParent;

implementation

var
Primary: TParent;

function GetPrimary: TParent;
begin
if Primary = nil then TParent.Create;
Result := Primary
end;

constructor TParent.Create;
begin
if Primary = nil then
Primary := Self
else
if ClassType = TParent then
raise Exception.Create("Primary object already exists");
inherited;
Initialize
end;

destructor TParent.Destroy;
begin
if Primary = Self then Primary := nil;
inherited
end;

procedure TParent.Initialize;
begin
if Primary = Self
begin
... // Инициализация OpenGL.
... // Другой код, который должен выполняться только 1 раз.
end;
... // Инициализация еще чего-то, если надо
end;

procedure TChild.Initialize;
begin
inherited; // Унаследованная инициализация, кроме OpenGL.
... // Собственная дополнительная инициализация, если надо
AssignCurrentProps
end;

procedure TChild.AssignCurrentProps;
// Назначает текущие значения свойств объекта Primary
begin
Prop1 := Primary.Prop1;
Prop2 := Primary.Prop2;
... // И так далее
end;

Теперь:

1. Первый вызов TParent.Create будет создавать и инициализировать объект класса TParent, а кроме того будет инициализировать OpenGL и переменную Primary. Доступ к этому объекту извне модуля осуществляется через функцию GetPrimary, причем при первом ее вызове все создается и инициализируется автоматически.

2. При попытке вызвать TParent.Create во второй раз получим сообщение об ошибке, а второй объект создан не будет. Не будет выполнена и повторная инициализация OpenGL. Значение переменной Primary тоже не изменится - она по-прежнему будет указывать на первый объект TParent.

3. При вызове TChild.Create будет создан и принициализирован объект класса TChild. При этом повторная инициализация OpenGL не выполняется, а все нужные свойства свежесозданного объекта автоматически получат те же значения, которые они в данный момент имеют у объекта Primary.

4. Объектов класса TChild или его потомков может быть создано сколько угодно.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.033 c
7-42164
M@D
2003-09-01 22:53
2003.11.13
Shutdown XP


14-41967
Думкин
2003-10-10 05:09
2003.11.13
С днем рождения! 10 октября.


8-41744
Smok_er
2003-07-11 16:38
2003.11.13
Skinable Interface


14-42091
Nick Denry
2003-10-19 15:17
2003.11.13
Любознательность №1.


3-41076
BigVova
2003-10-23 15:02
2003.11.13
Поддерживают ли IBX изменения в FB 1.5?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский