2015-09-16 23 views
5

Bu kod neden bir derleyici hatasıyla sonuçlanmıyor? Örneğin, "CallMe" ye "belirsiz çağrı" hatası vermeyi beklerdim. Bu derleyici veya dilde bir hata mı? Bu, ünite adını ve işlev çağrısının önündeki bir noktayı kullanarak çalışabilir, ancak bu, kullanıcı kodlarını ve kitaplık kodunu isim çarpışmasına karşı korumaz. Kodunuzun bir şey yaptığını düşünüyorsunuz ama başka bir şey yaptı ve bu kötü. documentation kaynaktanNeden farklı birimlerde aynı imzalarla bir işlev çağırmıyor derleyici hatasıyla sonuçlanır?

uses 
    Unit2, Unit3; 

{$R *.lfm} 
{ TForm1 } 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
    ShowMessage(IntToStr(CallMe(5))); 
end; 

unit Unit2; 
{$mode objfpc}{$H+} 
interface 
uses 
    Classes, SysUtils; 
function CallMe(A: Integer) : Integer; 
implementation 
function CallMe(A: Integer) : Integer; 
begin 
    Result := A * 2; 
end; 
end. 

unit Unit3; 
{$mode objfpc}{$H+} 
interface 
uses 
    Classes, SysUtils; 
function CallMe(A: Integer) : Integer; 
implementation 
function CallMe(A: Integer) : Integer; 
begin 
    Result := A * -1; 
end; 
end. 
+5

Bu tasarım gereğidir: Derleme sırasında derleyicinin gördüğü en son olanı çağırır. Diğerini aramak isterseniz, ünite adını ve ardından isme bir nokta ekleyin. – MartynA

+0

Teşekkürler. Bu tasarımın ardında yatan motivasyonu bilmek istiyorum. Bu, hatalar için bir fırsat yaratır. Ana ünitenin Unit2'den orijinal olarak CallMe'yi kullandığını ve programcı B'nin gelip ünite3'ü eklediğini, çünkü oradan bir fonksiyona ihtiyaç duyduğunu ve yanlışlıkla CallMe'nin başka bir şeyle değiştirildiğini bilmediğini söyleyelim (uzun bir üniteyi çok fazla kod düşünün). Derler ve çalışır. Uyarı yok hata yok. Bir çalışma zamanı probleminden daha çok bir derleyici hatası istiyorum ve AVeryLongLibraryName.FunctionName çağrılarını istemiyorum ve belirsiz bir çağrı için her bir birimdeki her aramayı arayın. –

+1

Herhangi bir programlama dili hatalar için bir fırsat yaratır. Her şey: ne yaptığını bilmek zorundasın. Bu vakalar hakkında size ipuçları veren harici araçlar var. –

cevap

13

: iki tane, aynı isimde bir değişken, sabit, tipi, prosedür veya işlev bildirmek durumunda

derleyici kullanımları madde son belirtilen biriminden birini kullanan . (Eğer bir eleme eklemek gerekir, diğer birimden tanımlayıcı erişmek için:. UnitName.Identifier) ​​

+0

Anladım.Bunun çok şaşırtıcı ve benim görüşümde tehlikeli davranış olduğunu söylemeliyim. Bir projeye daha sonra eklenen bir kitaplık, eski koddakiyle aynı imzalı bir işleve sahipti ve eski kod, yeni işlevi kullanmaya başladı çünkü yeni birim, kullanım cümlelerinde en son eklenmişti ve yeni işlevde bir hata vardı ve farklı şekilde çalıştı. sorun yarattı. Bu bir derleyici hatası seçeneğine dönüştürebileceğini biliyor muydunuz, bu bir daha kazara olmaz mı? –

+0

Bu davranıştan dolayı TP4 günlerinden beri yaşadım ve asla isim çatışmalarıyla ilgili hiçbir problem yaşamadım. Bu durumu belirtmek için ipucu/uyarı/hata seçeneği yoktur. Kod içgörüsü, işlevlerin hangi birime ait olduğunu göstermek için yardımcı olabilir. –

+0

@ user2304430: Bir hataya dönüştürülmesinin bir yolu yoktur, çünkü bu bir hata değildir. –

2

olarak, tasarım gereğidir söyledi yığın tabanlı bir yaklaşım kullanarak birimleri ve ayrıştırır gelen derleyici yükleri sembolleri Bir sembol aramak için son yüklenen ilk yüklenene kadar yüklenir. Önişlemci durumu, yine de küresel duruma doğrudan birleştirilir.

Çapraz birim aşırı yükleme bir istisna olsa da. Her iki işlevi de aşırı yüküyle işaretlerseniz; yönergesi, hata (bla testte işlevin adıydı)

[dcc32 Error] test.dpr: E2251 Ambiguous overloaded call to 'bla' 
    Unit1.pas(8): Related method: procedure bla; 
    Unit2.pas(8): Related method: procedure bla; 

iki farklı imzalar varsa, en iyi eşleşen birini seçecektir olsun.

çapraz aşırı yükleme daha yeni bir özelliktir, ancak tam olarak ne olduğunu hatırlamıyorum. Benim tahminim D2006.