2016-04-12 37 views
4

Kendimi öğretiyorum ve bu nedenle çok fazla terminoloji aşina değilim. Buna googling ile cevabı bulamıyorum: Sanal bir işleve "doğrudan" karşı "sanal" nedir?Sanal bir işleve "Doğrudan" ve "sanal" çağrıya çağrı

Bu, teknik açıdan değil, terminolojiyle ilgilidir. Bir aramanın "hemen hemen" ve "neredeyse" olarak tanımlandığı zaman soruyorum. Bu kavramların uygulanması ile ilgili vtables veya başka bir şey ile ilgili değildir.

X a;   // object of known type 
a.myfunc(); // will call X::myfunc() directly  
: Eğer tip X düz bir nesne için sanal işlevini çağırırsanız

class X { 
public: 
    virtual void myfunc(); 
}; 

, derleyici yani X::myfunct() doğrudan atıfta doğrudan bir çağrı oluşturur:

+0

sen gösterebilir misiniz. Bu terimi ilk defa duyduğumda. – xvan

+0

https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx Derleyici inlining kuralları hakkında. arasında – antiHUMAN

+1

Olası kopyalar [Sanal Yöntem çağrısı ve VTable bağlamında Doğrudan Yöntem çağrısı arasındaki fark nedir?] (http://stackoverflow.com/questions/12041614/what-is-difference-between-virtual-method-call-and -direct-method-in-bağlamında) – xvan

cevap

8

Sorunuzun yanıtı, farklı kavramsal düzeylerde farklıdır.

kavramsal dil seviyesinde
  • gayri dönem "sanal çağrı" genellikle aramada kullanılan nesne dinamik tip uyarınca çözülmesi aramalar anlamına gelir. C++ dil standardına göre, bu işlevin nitelikli adı kullanan aramalar hariç, sanal işlevlere yapılan tüm çağrılar için geçerlidir. Yöntemin nitelikli adı çağrısında kullanıldığında, çağrı genellikle insanlar "acil nesneler üzerinden yapılan sanal fonksiyonlara çağrıları söylüyorlar duyabiliyorum "doğrudan çağrı"

    SomeObject obj; 
    SomeObject *pobj = &obj; 
    SomeObject &robj = obj; 
    
    obj.some_virtual_function(); // Virtual call 
    pobj->some_virtual_function(); // Virtual call 
    robj.some_virtual_function(); // Virtual call 
    
    obj.SomeObject::some_virtual_function(); // Direct call 
    pobj->SomeObject::some_virtual_function(); // Direct call 
    robj.SomeObject::some_virtual_function(); // Direct call 
    

    Not olarak adlandırılır sanal değil ". Ancak, dil belirtimi bu bakış açısını desteklemiyor. Dile göre, sanal işlevlere yönelik tüm kalifiye olmayan çağrılar aynıdır: bunlar, nesnenin dinamik tip dinamiklerine uygun olarak çözülür. Bu [kavramsal] anlamda hepsi sanal sanal. Uygulama düzeyinde, "sanal arama" terimi, genellikle, sanal işlevlerin standart olarak gerekli işlevlerini uygulayan, bazı uygulama tanımlı mekanizma yoluyla gönderilen çağrıları ifade eder. Tipik olarak, çağrıda kullanılan nesne ile ilişkili Sanal Yöntem Tablosu (VMT) ile uygulanır. Ancak, akıllı derleyiciler, sanal görevleri gerçekten yapmak zorunda olduklarında, yani nesnenin dinamik türü derleme zamanında bilinmediğinde, yalnızca sanal işlevlere çağrı yapmak için kullanacaktır. Diğer tüm durumlarda, derleyici, çağrı resmi olarak kavramsal düzeyde “sanal” olsa bile, yöntemi doğrudan aramak için çaba gösterecektir.Örneğin, çoğu zaman, anlık nesnesi ile yapılan sanal işlev çağrıları (bir işaretçiye veya nesneye başvuru olarak) doğrudan çağrılar (VMT gönderimi dahil edilmeden) olarak uygulanır. Aynı nesnenin yapıcı ve yoketme Tabii

    SomeObject obj; 
    SomeObject *pobj = &obj; 
    SomeObject &robj = obj; 
    
    obj.some_virtual_function(); // Direct call 
    pobj->some_virtual_function(); // Virtual call in general case 
    robj.some_virtual_function(); // Virtual call in general case 
    
    obj.SomeObject::some_virtual_function(); // Direct call 
    pobj->SomeObject::some_virtual_function(); // Direct call 
    robj.SomeObject::some_virtual_function(); // Direct call 
    

    yapılan sanal fonksiyonlarına anında aramalar için geçerlidir, bu ikinci anlamda, hiçbir şey vmt ilgili olmadan doğrudan çağrılar gibi sanal fonksiyonları (üzere herhangi aramaları uygulamaktan derleyici engeller derleyici, derleme zamanında nesnenin dinamik türünü belirlemek için yeterli bilgiye sahipse). Yukarıdaki basit örnekte, herhangi bir modern derleyici tüm çağrıları doğrudan arama olarak gerçekleştirebilmelidir. Eğer * doğrudan ilgili * okumak nerede

+0

Yani ne diyorsunuz, bir nesneye bir işaretçi ile, hangi türetilmiş (veya temel) sınıfının vitrual fonksiyon aramak istiyorum? Örneğin, bir temel sınıfa işaretçiysem ve temel sınıftaki [sanal] işlevini, türetilmiş bir sınıftan bir geçersiz kılmayı çağırmak istediğimi belirtirseniz, o zaman doğrudan bir çağrı olur, çünkü derleme zamanında çözülebilir? – antiHUMAN

+1

@antiHUMAN: Evet, sanal dağıtımı bastırmak ve temel sınıf sürümünü çağırmak istiyorsanız, bunu nitelikli bir ad kullanarak yapabilirsiniz. Aslında, bu, türetilmiş sınıf sürümden sanal işlevlerin taban sınıfı sürümünü çağırdığınızda/kullandığınızda kullandığınız sözdizimidir. void Türetilmiş :: foo() {Temel :: foo(); } '. Bu durumda, nesne işaretçisi örtülüdür (açık sürüm "this-> Base :: foo()'). – AnT

+0

Evet, bunu yıllar önce "standart C++ incilinde" okuduğumu hatırlıyorum ve bu kavramı anlıyorum. Bu, doğrudan vs sanal çağrıların neden derleyici inilleme üzerinde bir etkiye sahip olabileceğini kesinlikle açıklıyor. Gerçekten iyi bir cevap verdin. – antiHUMAN

5

Eğer bu sınıfı olduğunu varsayalım

Sanal işlevini bir işaretçi dizini veya bir başvuru yoluyla çağırırsanız, işaret edilen nesnenin gerçekten sahip olacağı net değildir. Bu X'in olabilir ama aynı zamanda Sonra derleyici sanal bir arama, yani fonksiyon adrese işaretçiler bir tablo kullanmak yapacak X türetilen bir tür olabilir:

İşte
X *pa;  // pointer to a polymorphic object 
...   // initialise the pointer to point to an X or a derived class from X 
pa->myfunc(); // will call the myfunc() that is related to the real type of object pointed to  

kod bir online simulation var . İlk durumda, üretilen derlemenin işlev adresini çağırdığını görürsünüz, ikinci durumda, derleyici bir kayıttaki bir şeyi yükler ve bu kaydı kullanarak dolaylı bir çağrı yapar (yani aranan adres "zor değil" -wired "ve çalışma zamanında dinamik olarak belirlenecektir".

+0

Lütfen teknik dilde farklılıklara dikkat eden sadece bir kodun dışında bir açıklama ekleyin. –

+0

Normalde bir "doğrudan" işlev çağrısı ile kastedilenin bu olduğundan emin değilim. a.myfunc '() çağrısı hala bu sanal işlevine bir çağrı olabilir ve bu sanal olarak işlevim ilan başka bir sınıftan devralabilmesi sınıfı X değiştirilirse, aslında, daha sonra tam olarak hangi işlevim çağrılan o X veya temel sınıfın bir üyesi olmadığı gibi, kesinlikle "X" vardır hayır türetilmiş sınıfları, neden bir polimorfik nesne olarak kabul edilir beri sınıf X'te –

+0

geçersiz oluyor bağlıdır? Ayrıca 'final' doğrudan tekrar arama yapacak mı? – antiHUMAN