我想知道是否有可能没有直接调用任何构造函数的对象实例。这样的事情:
var
aObject : TMyObject;
begin
aObject.MyMethod; //will cause an AV, but is it possible?
end;
编辑:
我知道静态方法,但那不是我想要的。我正在寻找一种方法来调用构造函数而无需显式调用它。
答案 0 :(得分:12)
Delphi的对象都是堆分配的:你不能简单地声明一个对象并在其上调用方法,就像你在C ++中所做的那样,你必须调用一个构造函数来分配和设置内存。但请注意,即使在C ++中,实际上在调用构造函数时也是如此!
也许你可以逃脱记录而不是对象?例如:
type
TMyObject = record // name intentionally left as in OP's code
procedure MyMethod;
end;
procedure TMyObject.MyMethod;
begin
// Do something
end;
// Use example:
procedure Test;
var MyObject: TMyObject; // TMyObject is a record so it is stack-allocated
begin
MyObject.MyMethod; // Works.
end;
答案 1 :(得分:9)
如你所知,这很奇怪。但是,只要该方法是静态的并且不引用Self,那么这将起作用。
当然,这样的事情被称为class method。也许这就是你想要的?
type
TMyObject = class
class procedure MyClassMethod;
end;
...
TMyObject.MyClassMethod;
修改强>
您编辑了自己的问题。显然你知道所有关于静态方法的知识。您不希望在未初始化的对象上调用方法。
实际上,您现在声明您希望在未初始化的对象实例上调用方法的行为导致正在创建实例并调用该方法。
这是不可能的。任何为你调用构造函数的东西都没有魔力。
答案 2 :(得分:2)
您可以使用以下方式“分配”对象:
class function NewInstance: TObject; virtual;
此函数分配并初始化对象。之后,您可以将“create”构造函数作为它的正常函数调用(这是当您深入到程序集/ CPU视图时构造函数Create的工作方式)
答案 3 :(得分:2)
Delphi - 与C ++不同 - 没有自动创建构造函数的默认方法。
它与Delphi如何管理变量和范围有关。
在C ++中,当变量进入作用域时,它会自动调用构造函数。
你所追求的是RAII(资源获取是初始化)。
Barry Kelly(Delphi编译工程师之一)编写了interesting article about RAII in Delphi。
他的解决方案基于Delphi中接口的自动重新计数。
解释这个基本上意味着复制/粘贴他的文章,所以请按照上面的链接阅读。
- 的Jeroen
答案 4 :(得分:1)
没有。实际上有几个问题:
接口修复了1和3,但由于它们只是NILed,(2)需要发生,这不能完成。
此类问题需要在编译器级别实现。没有它,根本没有足够的事件来实现它。但是请解释一下你想要实现的目标。 有时候对于特定情况,有一些可以解决的问题,即使一般情况不可修复
答案 5 :(得分:1)
有一个肮脏的伎俩:
THackClass = class
private
function Sum(const A, B: Integer): Integer;
public
function HackMethod: Integer;
end;
function THackClass.HackMethod: Integer;
begin
Self := THackClass.Create;
try
Result := Sum(2, 3);
finally
Self.Free;
end;
end;
function THackClass.Sum(const A, B: Integer): Integer;
begin
Result := A+B;
end;
// and then
procedure TForm1.Button1Click(Sender: TObject);
var
HackClass: THackClass;
begin
ShowMessage(IntToStr(HackClass.HackMethod));
end;
当然,没有黑客写它会更自然:
TNonHackClass = class
private
function Sum(const A, B: Integer): Integer;
public
class function NonHackMethod: Integer;
end;
class function TNonHackClass.HackMethod: Integer;
var
instance: TNonHackClass;
begin
instance := TNonHackClass.Create;
try
Result := instance.Sum(2, 3);
finally
instance.Free;
end;
end;
function TNonHackClass.Sum(const A, B: Integer): Integer;
begin
Result := A+B;
end;
// and then
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(TNonHackClass.NonHackMethod));
end;
答案 6 :(得分:0)
正如David所说,你应该从帮助中看看Class方法:
大多数方法都称为实例 方法,因为它们在一个上运行 对象的单个实例。一个 class方法是一种方法(除了 对类进行操作的构造函数 而不是对象。那里有两个 类方法类型:普通类 方法和类静态方法。
除了查看类方法之外,您还可以使用现在具有方法能力的记录。
unit test;
interface
uses
SysUtils,
Classes;
type
TMyRecord = record
FieldA:String;
FieldB:String;
procedure MyMethod(const Param1:Integer);
end;
procedure DoSomething(const Param:Integer);
implementation
procedure DoSomething(const Param:Integer);
var
Rec:TMyRecord;
begin
Rec.MyMethod(Param); //no constructor needed
end;
procedure TMyRecord.MyMethod(const Param1:Integer);
begin
//do something coolio here
end;
end.
答案 7 :(得分:0)
你也可以这样做,虽然我不明白你为什么要这样做:
unit Unit2;
interface
type
TMyClass = class
public
class function GetNew: TMyClass;
function Hello: TMyClass;
end;
implementation
{ TMyClass }
class function TMyClass.GetNew: TMyClass;
begin
Result := TMyClass.Create();
end;
function TMyClass.Hello: TMyClass;
begin
ShowMessage( 'hello' );
Result := Self;
end;
procedure CallMyClass();
begin
TMyClass.GetNew.Hello.Free;
// or
with TMyClass.GetNew do
try
Hello;
finally
Free;
end;
end;