2010-11-20 24 views
2

"Güvenli olmayan sanal işlev" ile, tanı amaçlı olarak ayrıca uygulamaları olan (http://www.gotw.ca/gotw/031.htm numaralı belgede açıklandığı gibi) saf sanal işlevleri kastediyorum.Bu, kusurlu sanal işlevleri uygulamak için yasal bir yol mu?

bunları uygulamak için koşer yolu yapmaktır:

class Foo 
{ 
public: 
    ... 
    virtual void Bar() = 0; 
}; 

void Foo::Bar() { assert(false); } 

Ama bu sınıf saf sanal yöntemlerin bir numarası vardır özellikle, biraz can sıkıcı. Ayrıca, birisinin yanlışlıkla karşılık gelen bir uygulama eklemeden yanlışlıkla yeni bir sanal işlev eklemediğinden emin olmak zor.

class Foo 
{ 
public: 
    ... 
    virtual void Bar() = 0 
    { 
     assert(false); 
    } 
}; 

ama C++ standardı açıkça (ISO C++ 2003 standardında bölüm 10.4/2) Bu izin vermiyor:

İdeal ne yapmak istiyorum olduğunu.

Alternatif olarak, aşağıdaki kesmeyi düşündüm. İlgili Foo.cpp kaynak dosyada sonra

#ifndef ABSTRACT_METHOD 
#define ABSTRACT_METHOD = 0 
#endif 

class Foo 
{ 
public: 
    ... 
    virtual void Bar() ABSTRACT_METHOD; 
}; 

ve: tek derlenmiş uygulamasını alır böylece

#define ABSTRACT_METHOD { assert(false); } 

#include "Foo.h" 

... 

Foo.h başlığında.

Yasal mıdır?

+0

Eh, kaynak dosyada bir sahte '' 'olurdu ... –

+0

@Oli Charlesworth: Doğru, ama bunun doğal olarak yanlış bir şey var mı? Makro tanımına ''' takibi için sorumluluk taşıyarak kolayca önlenebilir. – jamesdlin

+1

@james: Evet, bunun bir derleyici hatası olacağına inanıyorum. Bildiğim kadarıyla tamir edilebilir olduğunu biliyorum, ama bu bir tesadüfi gözlemdi, bir eleştiri değil ... –

cevap

4

Hayır, yasal değil. Bir tanım kuralı, bir sınıfın bir programda (farklı çeviri birimlerinden) çok sayıda tanımlamaya sahip olabileceğini, ancak bu tanımların hepsinin, birbirinin aynı olan diziler dizisinden (3.2/5) oluşması gerektiğini söylemektedir. ABSTRACT_METHOD bir önişleme belirtecidir (makro değiştirmeden önce), ancak bu yeterince iyi değil.

Yani .cpp dosyanız geçerli olarak başlıkta yer alan başka bir .cpp ile aynı programda kullanılamaz.

+1

Darn, bundan korktum. Beni standardın ilgili bölümüne yönlendirdiğiniz için teşekkür ederim. Sanırım bu, __declspec (dllimport) 've' __declspec (dllexport) 'özniteliklerinin teknik açıdan standart bir bakış açısından yasal olmadığı anlamına gelir. – jamesdlin

+1

@jamesdlin: Teknik olarak evet, '__declspec 'ayrılmış bir addır, standart söz konusu olduğunda, onu içeren bir program kesinlikle uygun değildir. Program yine de Microsoft tarafından tanımlanan C++ lehçesi için geçerli olabilir ve eğer bu belgeler ODR'yi (açık ya da dolaylı olarak) rahatlatırsa, o zaman sorun yoktur. –

+0

Belki de bir orta zemin, iç geliştirme (derleyicinin tamamlanmamış türetilmiş sınıfları yakalamasına izin vermek) için ABSTRACT_METHOD'un farklı şeyler olmasına izin vermek olabilir; ancak bu, diğer her yerde saplama uygulaması olmasına izin vermektir. – jamesdlin

0

Geçerli olup olmadığını yanıtlayamıyorum. Ancak, sınıfınızın kullanıcısı, kaynak dosyada türetilmiş bir sınıf bildirirse, derleyici, bu türetilmiş sınıfta Bar() uygulanması gerektiğini zorunlu kılmaz (çünkü = 0'u görmez). Bunu tek başıma böyle yapmamanın bir nedeni olacağını düşünürdüm.

+0

Bu adil bir nokta. Codebase'imiz için bir sorun değildir, çünkü genellikle sınıfları ayrı dosyalara ayırırız.Başka bir yaklaşım, makroyu uygulama sürümünü tanımlayan, çeşitli soyut temel sınıf başlıklarını içeren ve başka hiçbir şey yapmayan tek bir ayrı kaynak 'impureVirtualStubs.cpp' dosyasına sahip olmak olacaktır. – jamesdlin