Düşündüğünüz sınırlamanın anlambilim ile ilgili olmadığını (başlatma işlemi aynı dosyada tanımlanmışsa neden bir şey değiştirmeli?) Değil de geriye doğru uyumluluk nedenleriyle kolayca değiştirilemeyeceği için C ++ derleme modeline bağlı olduğunu düşünüyorum. ya çok karmaşık hale gelir (aynı zamanda yeni bir derleme modelini ve mevcut olanı aynı anda destekler) ya da mevcut kodu derlemeye izin vermez (yeni bir derleme modeli ekleyerek ve mevcut olanı bırakarak).
C ++ derleme modeli, (başlık) dosyalarını dahil ederek bildirimleri bir kaynak dosyaya içe aktardığınız C'nin modelinden kaynaklanır. Bu şekilde, derleyici, içerdiği tüm dosyaları ve bu dosyalardan içerilen tüm dosyaları yinelemeli olarak içeren tam bir büyük kaynak dosyayı görür. Bunun IMO'ya büyük bir avantajı vardır, yani derleyicinin uygulanmasını kolaylaştırır. Tabii ki, dahil edilen dosyalara herhangi bir şey yazabilirsiniz, yani hem bildirimler hem de tanımlar. Başlık dosyalarına açıklamaları ve .c veya .cpp dosyalarına tanımları koymak iyi bir uygulamadır.
Öte yandan, derleyicinin çok iyi bildiği bir derleme modeline sahip olmak, başka bir modülde tanımlanmış bir genel sembol bildirgesini ithal etmek mi yoksa, tarafından sağlanan bir genel sembol tanımını derlemek mi mümkündür? mevcut modül . Sadece ikinci durumda, derleyici bu sembolü (örneğin bir değişken) geçerli nesne dosyasına koymalıdır.
Örneğin, GNU Pascal'da şöylea
bir dosyaya bir birim yazabilirsiniz a.pas
:
unit a;
interface
var MyStaticVariable: Integer;
implementation
begin
MyStaticVariable := 0
end.
burada global değişken aynı kaynak dosyada bildirilir ve başlatılır.
Ardından, a'yı alıp global değişkeni kullanan farklı birimleriniz olabilir
MyStaticVariable
, örneğin bir birim b ( b.pas
):
unit b;
interface
uses a;
procedure PrintB;
implementation
procedure PrintB;
begin
Inc(MyStaticVariable);
WriteLn(MyStaticVariable)
end;
end.
ve bir c ( c.pas
) birimi :
unit c;
interface
uses a;
procedure PrintC;
implementation
procedure PrintC;
begin
Inc(MyStaticVariable);
WriteLn(MyStaticVariable)
end;
end.
Sonunda b ve c birimlerini ana programda kullanabilirsiniz m.pas
:
program M;
uses b, c;
begin
PrintB;
PrintC;
PrintB
end.
Bu dosyaları ayrı ayrı derleyebilirsiniz:
$ gpc -c a.pas
$ gpc -c b.pas
$ gpc -c c.pas
$ gpc -c m.pas
ve sonra bir çalıştırılabilir dosya üret:
$ gpc -o m m.o a.o b.o c.o
ve çalıştırın:
$ ./m
1
2
3
Buradaki hile, derleyici bir program modülünde bir kullanım yönergesi gördüğünde (örn. B.pas'da bir kullanımda) karşılık gelen .pas dosyasını içermez, fakat önceden derlenmiş bir .gpi dosyasını arar. arayüz dosyası ( belgelere bakın ). Bu .gpi
dosyalar, derleyici tarafından .o
her modül derlendiğinde dosyalar ile birlikte oluşturulur . Böylece genel sembol MyStaticVariable
nesne dosyasında sadece bir kez tanımlanır a.o
.
Java da benzer şekilde çalışır: derleyici A sınıfını B sınıfına alırsa, A sınıfına bakar ve dosyaya ihtiyaç duymaz A.java
. Böylece A sınıfı için tüm tanımlamalar ve ilklendirmeler tek bir kaynak dosyaya konulabilir.
C ++ 'a geri dönersek, C ++' da statik veri üyelerini ayrı bir dosyada tanımlamak zorunda olmanızın nedeni, C ++ derleme modeliyle, linker veya derleyici tarafından kullanılan diğer araçların getirdiği sınırlamalardan daha fazladır. C ++ 'da bazı sembollerin içe aktarılması, bildirimlerini geçerli derleme biriminin bir parçası olarak oluşturmak anlamına gelir. Bu, şablonların derlenme biçimleri nedeniyle, diğer şeylerin yanı sıra, çok önemlidir. Ancak bu, dahil edilmiş bir dosyada herhangi bir genel sembolü (fonksiyonlar, değişkenler, yöntemler, statik veri üyeleri) tanımlayamayacağınız / tanımamamanız gerektiği anlamına gelir, aksi takdirde bu semboller derlenmiş nesne dosyalarında çarpılabilir.