Yanıtlar:
Eğer (bir uygulama dosyası yazarken .cpp
, .cxx
, vb) derleyici bir oluşturur çeviri birimi . Bu, uygulamanızın kaynak dosyası ve içinde oluşturduğunuz tüm üstbilgilerdir #include
.
İç bağlantı , yalnızca bir çeviri birimi kapsamındaki her şeyi ifade eder .
Dış bağlantı , belirli bir çeviri biriminin ötesinde olan şeyleri ifade eder. Başka bir deyişle, tüm çeviri birimlerinin (veya nesne dosyalarının) birleşimi olan tüm program aracılığıyla erişilebilir .
const
değişkenlerin kuralı (ve amacının yanı sıra) hakkındaki soru burada tamamen eksik olduğu için eksiktir .
As dudewat söyledi harici bağlantı simgesi (işlev veya global değişken) programınızın ve tamamında mevcuttur demektir iç bunun tek tek erişilebilir olduğundan bağlantı araçlarının çeviri birimi .
Açıkça kullanarak bir sembolün bağlantıyı kontrol edebilir extern
ve static
anahtar kelimeleri. Bağlantı belirtilmezse, varsayılan bağlantı sembol olmayanlar ve semboller extern
için (dahili) içindir .const
static
const
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
static
İç bağlantı için kullanmak yerine, es yerleştirebileceğiniz anonim ad alanlarını kullanmak daha iyidir class
. Anonim ad alanları için bağlantı C ++ 98 ve C ++ 11 arasında değişmiştir, ancak asıl önemli olan diğer çeviri birimlerinden erişilememesidir.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
, diğer dosyada eşleşen bir bildiri vererek içerdiği dosyalara genişletilebilir .static
. Bu değişkenlerin iç bağlantıya sahip olduğu söylenir .Aşağıdaki örneği düşünün:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
beyan f
ile bir fonksiyonu olarak dış bağlantı (varsayılan). Tanımı bu dosyada veya başka bir çeviri biriminde (aşağıda verilmiştir) belirtilmelidir.max
bir tamsayı sabiti olarak tanımlanır. Sabitleri için varsayılan bağlantı olduğunu dahili . Bağlantısı anahtar kelimeyle harici olarak değiştirilir extern
. Artık max
başka dosyalardan da erişilebilir.n
bir tamsayı değişkeni olarak tanımlanır. İşlev gövdelerinin dışında tanımlanan değişkenler için varsayılan bağlantı harici değerdir .#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max
dış bağlantıya sahip olduğu beyan edilmiştir . max
Bazı dosyalarda (harici bağlantıyla) için eşleşen bir tanım görünmelidir. (1.cpp'de olduğu gibi)n
dış bağlantıya sahip olduğu beyan edilmiştir .z
olduğu belirlenen bir küresel değişken olarak iç bağlantı .nCall
belirtir . Varsayılan otomatik depolama sınıfına sahip yerel değişkenlerin aksine, her çağırma için bir kez değil, programın başında bir kez başlatılır . Depolama sınıfı belirticisi kapsamını değil, yerel değişkenin ömrünü etkiler.nCall
f()
nCall
f()
static
Not: Anahtar kelime static
çift rol oynar. Global değişkenlerin tanımlarında kullanıldığında, iç bağlantıyı belirtir . Yerel değişkenlerin tanımlarında kullanıldığında, değişkenin ömrünün işlevin süresi olmak yerine programın süresi olacağını belirtir.
Umarım yardımcı olur!
static
, tembel tek başlatmaya izin verir (global-ish nesnesine ihtiyacınız varsa yararlı olabilir, ancak global inşaat siparişi ile ilgili sorunlar nedeniyle ne zaman inşa edildiğini kontrol etmek zorunda kalır ve dinamik olarak ayıramazsınız kullanarak new
ima yolu ile bu) C ++ kullanmak gömülü sistemlerde bir sorun esas olduğu; daha derinlemesine başlatma düzenleri söz konusu nesne için gerekenin ötesine olabileceği görüşündedir.
'C' de farklı kapsam hakkında konuşalım
KAPSAM: Temelde bir şeyi ne kadar süreyle ve ne kadar uzağa görebiliyorum.
Yerel değişken: Kapsam yalnızca bir işlevin içindedir. RAM'in STACK alanında bulunur. Bu, bir işlev her çağrıldığında, işlev bağımsız değişkenleri de dahil olmak üzere o işlevin parçası olan tüm değişkenler yeni oluşturulur ve denetim işlevden çıktıktan sonra yok edilir. (İşlev her döndüğünde yığın temizlendiğinden)
Statik değişken: Bunun kapsamı bir dosya içindir. Dosyaya
bildirildiği her yerde erişilebilir . RAM'in VERİ bölümünde bulunur. Bu, yalnızca bir dosya içinde erişilebilir ve bu nedenle DAHİLİ bağlantı. Herhangi
diğer dosyaları bu değişkeni göremez. Aslında STATIC anahtar sözcüğü,
'C' de gizlenen bir miktar veri veya işlev sunmanın tek yoludur.
Global değişken: Bunun kapsamı tüm bir uygulama içindir. Uygulamanın her yerine erişilebilir bir formdur. Global değişkenler DATA segmentinde de bulunur, çünkü uygulamadaki her yere ve dolayısıyla EXTERNAL Linkage'a erişilebilir.
Varsayılan olarak tüm işlevler globaldir. Bir dosyadaki bazı işlevleri dışarıdan gizlemeniz gerekirse, statik anahtar kelimeyi işleve önek olarak ekleyebilirsiniz. :-)
Soru hakkında konuşmadan önce, çeviri birimi , program ve C ++ ile ilgili bazı temel kavramları (aslında bağlantı genel olarak bunlardan biridir) bilmek daha iyidir . Ayrıca kapsamın ne olduğunu da bilmeniz gerekir .
Bazı önemli noktaları vurgulayacağım, özellikle. önceki cevaplarda eksik olanlar.
Bağlantı , bir bildiriyle tanıtılan bir adın özelliğidir . Farklı adlar aynı varlığı (genellikle bir nesne veya işlev) gösterebilir . Dolayısıyla , bir varlığın bağlantısı hakkında konuşmak genellikle saçmalıktır, eğer varlığın sadece bazı belirli beyanlardan (genellikle bir beyan olsa da) benzersiz adıyla bahsedileceğinden emin değilseniz.
Bir nesnenin bir varlık olduğunu, ancak bir değişkenin olmadığını unutmayın. Bir değişkenin bağlantısı hakkında konuşurken, aslında belirtilen varlığın adı (belirli bir bildirimle tanıtılan) söz konusudur. İsmin bağlantısı üçünden birindedir: bağlantı, iç bağlantı veya dış bağlantı yok.
Farklı çeviri birimleri, aynı bildirimi başlık / kaynak dosyasıyla (evet, standardın ifadesidir) ekleyerek paylaşabilir. Böylece aynı adı farklı çeviri birimlerinde ifade edebilirsiniz. Bildirilen adın harici bir bağlantısı varsa, adla belirtilen varlığın kimliği de paylaşılır. Bildirilen adın iç bağlantısı varsa, farklı çeviri birimlerinde aynı ad farklı varlıkları ifade eder, ancak aynı çeviri biriminin farklı kapsamlarındaki varlığı ifade edebilirsiniz. Adda bağlantı yoksa, varlığı diğer kapsamlardan yönlendiremezsiniz.
(Hata ... Yazdığım şeyin standart ifadeleri tekrarlamak olduğunu gördüm ...)
Dil spesifikasyonu kapsamında olmayan bazı kafa karıştırıcı noktalar da vardır.
__attribute__
veya__declspec
) veya derleyici seçeneklerini kullanırsanız ve görüntü bir çeviri biriminden çevrilen programın tamamı veya nesne dosyası değildir, dolayısıyla hiçbir standart kavram bunu doğru bir şekilde tanımlayamaz. Sembol, C ++ 'da normatif bir terim olmadığından, lehçelerin ilgili uzantıları yaygın olarak benimsenmiş olsa bile, sadece bir uygulama detayıdır.Ad kapsamı içinde bağlantı kuralı const
değişkeni özel bir şey (ve özellikle farklıdır const
ayrıca tanımlayıcılar bağlantı kavramı vardır C dilinde dosya kapsamında beyan edilen nesne). Yana ODR C tarafından zorlanır ++ hiçbir daha fazla aynı değişken veya fonksiyonunun bir tanım daha devam hariç tüm program oluştu önemlidir inline
fonksiyonları . Böyle özel bir kural yoksa, birden çok çeviri biriminin içerdiği (veya bir çeviri birimi tarafından birden çok kez dahil edilen) bir başlıkta veya kaynak dosyada (genellikle bir "başlık dosyası") başlatıcıları const
olan en basit const
değişken bildirimi (örn. = xxx
), nadiren de olsa) bir programda ODR'yi ihlal eder, bu daconst
Değişken olarak bazı nesne benzeri makroların değiştirilmesi mümkün değildir.
Bence C İç ve Dış Bağlantı ++ açık ve özlü bir açıklama verir:
Bir çeviri birimi bir uygulama (.c / .cpp) dosyasına ve içerdiği tüm başlık (.h / .hpp) dosyalarına karşılık gelir. Böyle bir çeviri biriminin içindeki bir nesne ya da işlev dahili bağlantıya sahipse, o sembol yalnızca o çeviri birimindeki bağlayıcı tarafından görülebilir. Bir nesnenin veya fonksiyonun harici bağlantısı varsa, bağlayıcı diğer çeviri birimlerini işlerken de görebilir. Statik anahtar kelime, genel ad alanında kullanıldığında, bir sembolü dahili bağlantıya sahip olmaya zorlar. Extern anahtar sözcüğü, dış bağlantıya sahip bir sembolle sonuçlanır.
Derleyici, sembollerin bağlantısını varsayılan olarak ayarlar:
Sabit olmayan global değişkenler varsayılan olarak harici bağlantıya sahiptir Sabit küresel değişkenler varsayılan olarak dahili bağlantıya
sahiptir İşlevler varsayılan olarak harici bağlantıya sahiptir
Bağlantı, aynı adlara sahip tanımlayıcıların, bu tanımlayıcılar farklı çeviri birimlerinde görünse bile aynı nesneyi, işlevi veya başka bir varlığı ifade edip etmediğini belirler. Bir tanımlayıcının bağlantısı, nasıl bildirildiğine bağlıdır. Üç tür bağlantı vardır:
Yalnızca C ++ : C ++ ve C ++ olmayan kod parçaları arasında bağlantı olabilir, buna dil bağlantısı denir .
Kaynak: IBM Program Bağlantısı
temel olarak
extern linkage
değişken tüm dosyalarda görünürinternal linkage
değişkeni tek dosyada görülebilir.Açıklayın: const değişkenleri, başka türlü extern olarak bildirilmedikçe varsayılan olarak dahili olarak bağlanır
external linkage
const
global değişkeninternal linkage
extern const
global değişkenexternal linkage
C ++ 'da bağlantı hakkında oldukça iyi bir malzeme
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
C ++ dilinde
Dosya kapsamındaki ve bir sınıf veya işlevin içinde yuvalanmayan tüm değişkenler, bir programdaki tüm çeviri birimlerinde görülebilir. Buna harici bağlantı denir, çünkü bağlantı sırasında ad her yerde bu çeviri biriminin dışındaki bağlayıcı tarafından görülebilir.
Global değişkenler ve sıradan fonksiyonlar dış bağlantıya sahiptir.
Dosya kapsamındaki statik nesne veya işlev adı, çeviri biriminde yereldir. Buna İç Bağlantı denir
Bağlantı yalnızca bağlantı / yükleme zamanında adresleri olan öğeleri ifade eder; bu nedenle, sınıf bildirimleri ve yerel değişkenlerin bağlantısı yoktur.