Форум: "Основная";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
ВнизOperator not applicable to this operand type Найти похожие ветки
← →
XP (2005-03-01 12:24) [0]Надоело об стену стучаться головой. Подскажите, пожалуйста.
unit urInterfaces;
interface
type
IrIniFile = interface
function GetData: string; stdcall;
end;
...
//-----------------------------------------unit urIniFile;
interfaces
uses
urInterfaces;
type
TrIniFile = class(TObject, IrIniFile)
protected
function GetData: string; stdcall;
end;
implementation
uses
urCore;
...
//-----------------------------------unit urCore;
interface
uses
urInterfaces, urIniFile;
type
TrCore = class
private
m_IniFile: IrIniFile;
public
constructor Create;
end;
implementation
constructor TrCore.Create;
begin
m_IniFile := TrIniFile.Create as IrIniFile; // остановка компилятора
end;
На месте остановки пишет: Operator not applicable to this operand type
Вместе с тем, TrIniFile явно объявлен как class(TObject, IrIniFile).
Кроме того, IDE упорно отказывается "ходить" по исходникам по Ctrl + LeftClick.
Все файлы лежат в одной папке. Больше нигде исходников нет - только в этой папке. То-есть, использование разных DCU исключено - специально перепроверил.
Что он хочет-то?... Где это я так сильно споткнулся?...
← →
Димон (2005-03-01 12:26) [1]гуид проставь
ctrls+shilf+g ^)))
← →
XP (2005-03-01 12:30) [2]Спасибо, Димон, за подсказку, но он там стоит.
Я в примере не привел, чтобы не засорять текст.
← →
Димон (2005-03-01 12:33) [3]
> Спасибо, Димон, за подсказку, но он там стоит.
слабо верится. Должно работать, если он стоит :)
Ты где его ставишь? Надо же внутри описания интерфейса. А ты где?
И вообще, почему потомок TObject? У тя работать не дожно, т.к. ты не реализовал _AddRef и прочие методы?
← →
clickmaker © (2005-03-01 12:38) [4]угу, должно быть TInterfacedObject
← →
Димон (2005-03-01 12:40) [5]или самому реализовать нужные методы
← →
Чапаев © (2005-03-01 12:42) [6]m_IniFile := TrIniFile.Create; -- а так?
← →
XP (2005-03-01 12:45) [7]Ё... ну, упростил, чтобы проще было понять.
Вот, реальные интерфейсы и классы:
//----------------------------unit urInterfaces;
interface
type
IrComponent = interface(IUnknown)
["{898ADB4F-A411-4AF3-96E6-F2A4CB21F0E4}"]
// Возвращает имя компонента в системе
function Get_ComponentName: string; stdcall;
// Отображает окно свойств компонента (с использованием службы представления)
procedure ShowPropertiesDialog; stdcall;
(* Properties ****)
property ComponentName: string read Get_ComponentName;
end;
...
IrIniFile = interface(IrComponent)
["{CA6FAC79-F754-4A03-8D63-00FE2A2A4C83}"]
// Возвращает полный путь к папке модулей.
function Get_ModulePath: string; stdcall;
// Возвращает имя основной базы данных.
function Get_MainDBName: string; stdcall;
// Возвращает полный путь к файлу базы данных.
function Get_MainDBFileName: string; stdcall;
// Выводит диалог выбора start-файла при запуске системы.
function DialogConnect: TrResult; stdcall;
(* Properties ****)
property ModulePath: string read Get_ModulePath;
property MainDBName: string read Get_MainDBName;
property MainDBFileName: string read Get_MainDBName;
end;
...
IrCore = interface(IrComponent)
["{73DA798B-DADA-43B8-9785-83F6ACD45520}"]
function Get_IniFile: IrIniFile; stdcall;
(* Properties ****)
property IniFile: IrIniFile read Get_IniFile;
end;
//----------------------------unit urCommon;
interface
uses
urInterfaces;
type
TrComponent = class(TObject, IrComponent)
private
m_iRefCount: integer;
protected
function _AddRef: integer; stdcall;
function _Release: integer; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
protected
procedure ShowPropertiesDialog; virtual; stdcall; abstract;
function Get_ComponentName: string; virtual; stdcall; abstract;
public
constructor Create; virtual;
destructor Destroy; override;
end;
//----------------------------unit urIniFile;
interface
uses
urInterfaces, urCommon;
type
TrIniFile = class(TrComponent, IrIniFile)
private
m_IniFile: TIniFile;
m_MainDBSection: string;
protected
function DialogConnect: TrResult; stdcall;
function Get_ComponentName: string; override; stdcall;
function Get_MainDBFileName: string; stdcall;
function Get_MainDBName: string; stdcall;
function Get_ModulePath: string; stdcall;
procedure ShowPropertiesDialog; override; stdcall;
public
constructor Create; override;
destructor Destroy; override;
end;
// --------------------------------unit urCore;
interface
uses
urInterfaces, urCommon, urIniFile...;
type
TrCore = class(TrComponent, IrCore)
private
m_IniFile: IrIniFile;
...
public
constructor Create; override;
...
end;
implementation
constructor TrCore.Create;
begin
inherited Create;
m_IniFile := TrIniFile.Create as IrIniFile; // стоп...
...
end;
← →
XP (2005-03-01 12:48) [8]m_IniFile := TrIniFile.Create; -- а так?
Как ни странно, но это компилятор воспринимает. :)
Спасибо.
Только вот, кто бы еще объяснил, чем его не устраивает конструкция с использованием as?
← →
VMcL © (2005-03-01 12:48) [9]>>XP (01.03.05 12:45) [7]
В данном случае "as" не нужен, AFAIR:m_IniFile := TrIniFile.Create;
← →
Димон (2005-03-01 12:50) [10]
> Как ни странно, но это компилятор воспринимает. :)
правда странно. Я обычно, правда,не делаю приведение сразу после конструктора. Обычо через вр. перем.а := TSomeClass.Create;
i := a as ISomeInt;
Тоже было бы интересно послушать мнения окружающий, почему так?
← →
Digitman © (2005-03-01 12:51) [11]
> XP (01.03.05 12:45) [7]
классы, реализующие интерфейсы-наследники IUnknown, обязаны реализовывать как минимум 3 обязательных метода интерфейса IUnknown: QueryInterface(), _AddRef() и _Release()
класс TInterfacedObject УЖЕ реализует эти методы, так что любые его наследники уже не обязаны реализовать их самостоятельно
← →
Чапаев © (2005-03-01 12:52) [12]as -- оператор приведения классов. А ты пытаешься class as interface.
Интерфейсу можно присваивать интерфейсы и классы, которые реализуют данный интерфейс.
← →
Димон (2005-03-01 12:52) [13]
> [11] Digitman © (01.03.05 12:51)
он же реализацию не привел. Может ему подсчет ссылок не нужен :)
← →
XP (2005-03-01 12:53) [14]2 VMcL
Не нужен.
Но и не мешает.
Он в коде остался как "наследие" динамически подключаемого объекта. Раньше вместо TrIniFile.Create стояла функция LoadModule, возвращавшая интерфейс IrComponent - поэтому и использовалось явное приведение. И никому "as" не мешало.
Why?
← →
Димон (2005-03-01 12:53) [15]
> [12] Чапаев © (01.03.05 12:52)
> as -- оператор приведения классовi: IInt1;
i2: IInt2;
i := i2 as IInt1;
тоже работает. Т.е. as это не только для классов :)
← →
XP (2005-03-01 12:56) [16]>>as -- оператор приведения классов
Ээээ... А тут позвольте не согласиться. См. "Interface querying".
You can use the as operator to perform checked interface typecasts. This is known as interface querying, and it yields an interface-type expression from an object reference or from another interface reference, based on the actual (runtime) type of the object. An interface query has the form
object as interface
where object is an expression of an interface or variant type or denotes an instance of a class that implements an interface, and interface is any interface declared with a GUID.
← →
XP (2005-03-01 12:59) [17]Так что же компилятору не понравилось в "as"? :)
← →
Чапаев © (2005-03-01 13:01) [18]приносю мои искренние пардоны.
← →
XP (2005-03-01 13:09) [19]2 Чапаев © (01.03.05 13:01) [18]
:)
2 All
И все же?...
← →
Digitman © (2005-03-01 13:18) [20]
> Димон (01.03.05 12:52) [13]
> он же реализацию не привел. Может ему подсчет ссылок не
> нужен
да мало ли чего ему не нужно !
коль метод декларирован в интерфейсе, и класс реализует этот интерфейс, значит класс ОБЯЗАН реализовать тем или иным образом ВСЕ методы этого интерфейса !
а уж подсчет ссылок он там будет делать или мух считать - это его личное дело)
> XP
так что - вперед, с песнями и плясками, декларировать и реализовывать все методы твоего интерфейса ... а уж потом и разговор будет насчет всего остального ..
← →
XP (2005-03-01 13:29) [21]2 Digitman
См. [7] - объявление классов TrComponent, TrIniFile
А потом и потанцуем... :)
← →
Digitman © (2005-03-01 13:39) [22]
> XP (01.03.05 13:29) [21]
> потом и потанцуем
нет, сначала мы потанцуем вокруг
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
← →
XP (2005-03-01 13:48) [23]нет, сначала мы потанцуем вокруг
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
К чему это выделение virtual? Чем это может помешать?
← →
Набережных С. © (2005-03-01 13:57) [24]У тебя IUnknown классом не реализуется. AS его у объекта запрашивать должен, тот ответит отказом, компилятор это знает.
← →
Digitman © (2005-03-01 13:59) [25]
> К чему это выделение virtual? Чем это может помешать?
разуваем глаза, читаем справку :
Methods cannot be declared as virtual, dynamic, abstract, or override. Since interfaces do not implement their own methods, these designations have no meaning.
декларация метода класса, реализующего интерфейс, должна в точности соответствовать декларации соотв.метода в декларации интерфейса, реализуемого этим классом
← →
Набережных С. © (2005-03-01 13:59) [26]Точнее даже так: IUnknown должен быть добыт из класса на этапе компиляции, а AS выльется запрос QueryInterface.
← →
Димон (2005-03-01 13:59) [27]
> [24] Набережных С. © (01.03.05 13:57)
> У тебя IUnknown классом не реализуется. AS его у объекта
> запрашивать должен, тот ответит отказом, компилятор это
> знает.
разве? разве iinteface не аналог iunknown и просто interface не эквивалент interface(IInteface)?
← →
Набережных С. © (2005-03-01 14:01) [28]
> Димон (01.03.05 13:59) [27]
А какая разница, аналог или нет? TObject никакой не реализует.
← →
Digitman © (2005-03-01 14:02) [29]
> Димон (01.03.05 13:59) [27]
> просто interface не эквивалент interface(IInteface)?
объявление IMyInterface = interface;
эквивалентно IMyInterface = interface(IUnknown);
подобно тому, что объявление TMyObject = class;
эквивалентно TMyObject = class(TObject);
← →
Набережных С. © (2005-03-01 14:03) [30]В общем, надо объявить так
TrIniFile = class(TObject, IUnknown, IrIniFile)
← →
Димон (2005-03-01 14:03) [31]
> [28] Набережных С. © (01.03.05 14:01)
Не-е-е-е, Ты что-то не то говоришь:))) Наверное в приведенном коде не до конца разобрался. :)
> [29] Digitman © (01.03.05 14:02)
Да знаю я :) Это наводящий вопрос бы [27] :)
← →
Набережных С. © (2005-03-01 14:04) [32]Или TInterfacedObject и не маяться...ну сами знаете чем:)
← →
Димон (2005-03-01 14:05) [33]
> [30] Набережных С. © (01.03.05 14:03)
А... так более понятно:) Прости, не понял сначала
← →
Набережных С. © (2005-03-01 14:05) [34]
> Димон (01.03.05 14:03) [31]
Да ты проверь, дяденька, попробуй, в CPU View загляни, ага. Хуже-то от этого не будет:)
← →
Димон (2005-03-01 14:06) [35]
> [34] Набережных С. © (01.03.05 14:05)
Я ужо извинился. Ты выразился не вполне понятно просто :)))
← →
XP (2005-03-01 14:13) [36]TrIniFile = class(TObject, IUnknown, IrIniFile)
IrIniFile порожден от IrComponent, который, в свою очередь, порожден от IUnknown. См. [7].
Смысл?
2 Digitman © (01.03.05 13:59) [25]
VCL - Classes.pasTComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
...
{ IInterface }
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
...
end;
Что сие может обозначать?...
← →
Набережных С. © (2005-03-01 14:13) [37]
> Димон (01.03.05 14:06) [35]
Дык время посмотри:) Когда писал, [33] еще не было. Да вроде и ничего такого не сказал...Но если все-таки обидел - искренние извинения, совершенно не хотел.
> Ты выразился не вполне понятно просто
Да, бывает со мной. Кажется, если мне очевидно, то и другим тоже. Есть такой грех:(
← →
Димон (2005-03-01 14:14) [38]
> 34] Набережных С. © (01.03.05 14:05)
да, интересная информация. Никогда об этом не задумывался, т.к. всегда iunknown реализовывал, даже если не пользовался TIntefacedObject.
Благодарю :)
← →
vuk © (2005-03-01 14:17) [39]to Digitman:
>декларация метода класса, реализующего интерфейс, должна в
>точности соответствовать декларации соотв.метода в декларации
>интерфейса, реализуемого этим классом
Значит так. Метод не может быть объявлен virtual при объявлении в интерфейсе (если так можно сказать, они там все virtual), но при реализации в классе метод может иметь любые модификаторы, которые не влияют на способ передачи параметров. В приведенном примере virtual написано именно в реализации.
← →
Набережных С. © (2005-03-01 14:17) [40]
> XP (01.03.05 14:13) [36]
> IrIniFile порожден от IrComponent, который, в свою очередь,
> порожден от IUnknown
С точки зрения реализации интерфейса объектом, это не имеет никакого значеня. Реализован только тот, который явно объявлен в классе или в его, класса, предках. Все предки интерфейса - побоку.
← →
Digitman © (2005-03-01 14:18) [41]
> Надоело об стену стучаться головой
конечно же больно)
нет бы - хрясь ! - легким движением руки унаследовать свой класс от TInterfacedobject ... так ведь - нет ! мы легких путей не ищем) ... нам геморрой в причинном месте дороже)
← →
Димон (2005-03-01 14:20) [42]
> [37] Набережных С. © (01.03.05 14:13)
Этта что получается, что все as для интерфейсов "ходят" через метод QueryInterface относительно IUnknown?
← →
Набережных С. © (2005-03-01 14:22) [43]Просто надо вспомнить, что каждый интерфейс в классе - таблица, и в каждой из них свои AddRef, Release и все остальные унаследованные интерфейсом методы.
← →
Набережных С. © (2005-03-01 14:22) [44]Просто надо вспомнить, что каждый интерфейс в классе - таблица, и в каждой из них свои AddRef, Release и все остальные унаследованные интерфейсом методы.
← →
Набережных С. © (2005-03-01 14:25) [45]
> Димон (01.03.05 14:20) [42]
Да, если Object as interface. Если interface as interface, то вызывается метод самого исходного интерфейса.
← →
Димон (2005-03-01 14:27) [46]
> [45] Набережных С. © (01.03.05 14:25)
Спасибо. Вообще говоря логично :)))
Полезная информация.
Где тут оценки ставят как на RSDN? :)))
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.049 c