2009-09-08 20 views
9

Bir sonraki durumum var: Tek bir statik kütüphanede widget oluşturmanız gerekiyor, bu da son uygulama ile bağlantılı olacak (visual C++ 9.0, qt 4.5). Bu statik pencere öğesi kitaplığı bazı kaynakları (simgeler) içerir ve birkaç .cpp dosyasından oluşur (her biri bağımsız pencere öğesi içerir). Bildiğim kadarıyla, "q_INIT_RESOURCE (resource_file_name)" çağrısıyla, statik kütüphanede (kaynaklar) kullanırsam qt kaynak sistemini başlatmalıyım.Statik kitaplığa yerleştirilmiş qt kaynaklarını başlatma

yerine benim ilk yaklaşım, ben başlatma kodu ile statik kütüphane projesinde ayrı init.cpp dosyası oluşturduk
 

#include <QAbstractButton> 

namespace { 
struct StaticLibInitializer 
{ 
    StaticLibInitializer() 
    { 
     Q_INIT_RESOURCE(qtwidgets_custom_resources); 
    } 
}; 
StaticLibInitializer staticLibInitializer; 
} 

// ... widget code .... 
 

(başlatma dahil önlemek için: I (statik kitaplığında her .cpp dosyasında) aşağıdaki kodu ile bu çözüldü kod her .cpp dosyasında), ama bu işe yaramadı.

Neden bu işe yaramadı?

StaticLibInitializer ile bu yaklaşım çeşitli derleyiciler ve platformlar arasında güvenli ve taşınabilir mi?

cevap

10

İşe yaramadı çünkü static initialization order fiasco numaralı telefondan vuruldunuz. Statik nesneleri ilklendiren kodunuzu, bu statik nesnelerin kullanıldığı çeviri birimini (kaynak dosya olarak okuyabilirsiniz) daha iyi hale getiremezsiniz. Yaptığın gibi değil. Bu statik nesneleri ilklendirmek için kullanmakta olduğunuz şemayı kullanmak istiyorsanız, yalnızca init.hpp başlığınıza yapılan bildirimleri taşıyın, ancak statik nesneleri kullanan her dosyada StaticLibInitializer staticLibInitializer; belirtileri bırakın.
Tavsiyenin yukarısında, her bir widget'ın sadece kendi kaynaklarını kullandığı varsayılmaktadır. Bir widget'ın kaynaklarının başka bir widget tarafından kullanıldığı durumunuz varsa, tekrar fiyasko statüsüne getirin. Yalnızca bir kez verilen kaynak başlatır StaticLibInitializer emin çarpın instantiations yapıp sonra size verilen çeviri birimi kullanacağız her kaynak için StaticLibInitializer örneğini bu

StaticLibInitializer 
{ 
    void initialize() 
    { 
     static Q_INIT_RESOURCE(qtwidgets_custom_resources); 
    } 

    StaticLibInitializer() 
    { 
     initialize(); 
    } 
} 

gibi kodu kullanarak bu durumu yönetebilirsiniz.

+0

Geçerli durumumda üç .cpp dosyam var (bunların her biri kendi widget'ını uygular, ikisi de .qrc dosyasından kaynak kullanır), ancak orijinal soruda verdiğim başlatma kodu, bunlardan yalnızca birinde ve tüm çalışmalarda ince (% 100, 50/50 değil). Bu yüzden anlayamıyorum, neden başlangıç ​​kodunu ayrı bir init olarak koydum.cpp dosyası Kaynaklarımı kullanamıyorum, ancak bu kodun widget'larından biri olan .cpp dosyasında her şey düzgün çalışıyorsa ... – cybevnm

+0

İşe yaramıyor, iyi çalışıyor ** şimdi ** :) Sadece kaza ile çalışıyor. Başka bir derleyiciyi veya aynı derleyicinin başka bir sürümünü kullanmaya başladığınız an çalışmayı durdurabilir. ** ** DOLAYLI DAVRANIŞ **. Şu anda çalışmasının nedeni, öncelikle widget'ların birindeki derleyici kodunda bir başlatma kodu bulunduğunda ** kaynaklarınızı ilk önce başlatmanızın ** sebebidir. Saf şans, başka bir şey değil. Programınızı% 0 güneşli bir günde çalışmak istemiyorsanız, * statik başlatma sırasından * kaçınmak için talimatları izleyin. –

+0

Derleyici tarafından derleme aşamasında tanımlanan statik başlatma sırasını mı, yoksa yeniden başlatma programları (yeniden derleme olmadan) arasında değişiklik olabilir mi? – cybevnm

6

Q_INIT_RESOURCE makrosu bir ad alanında kullanılamaz.

qt kılavuzundan alıntı yapmama izin verin: "Not: Bu makro bir ad alanında kullanılamaz. Ana()" den çağrılmalıdır.

inline void initMyResource() { Q_INIT_RESOURCE(myapp); } 

    namespace MyNamespace 
    { 
    ... 

    void myFunction() 
    { 
     initMyResource(); 
    } 
    } 

kendinizi neden ve nasıl tam olarak başarısız olur veya belirtilmemiş bir şekilde kullanırsak başarısız değildir bakınız: Ve hatta bu mümkün değilse, doğru yapmak nasıl bir örnek verir. İlgili kod QtCore'dadır.

+0

Ancak ilk yaklaşımda (statik kütüphanenin her .cpp dosyasına kod eklediğimde) bu ad (anonim ad alanıyla bile olsa). – cybevnm

+0

Yukarıdaki "inline" özelliğini kullanmak, bir derleyici tarafından kabul edilmeyeceğinden hiçbir garanti almadığınız için hiçbir şey satın almaz. * Bu anahtar kelimeye saygı göstermemek, C++ standardına uygundur. Yani bu * çözüm * varsayımına dayanıyorsa satır içi fonksiyonun satır içi olduğu anlaşılır. –

+1

'satır içi 'işlevler, özellikle ODR'ye geldiğinde, biraz farklı anlamlara sahiptir. Q_INIT_RESOURCE'un makro genişlemesini tüm platformlarda bilmediğimizi düşünürsek, gerekip gerekmediğini yargılamak zordur. Orada koymak kesinlikle mantıklı. – MSalters

İlgili konular