2011-10-16 19 views
39

böyle kod yok:Erişim arkadaşı fonksiyon sınıfında tanımlanan

#include <iostream> 

class A{ 

public: 
    friend void fun(A a){std::cout << "Im here" << std::endl;} 
    friend void fun2(){ std::cout << "Im here2" << std::endl; } 
    friend void fun3(); 
}; 

void fun3(){ 
    std::cout << "Im here3" << std::endl; 
} 

int main() 
{ 
    fun(A()); // works ok 
    //fun2(); error: 'fun2' was not declared in this scope 
    //A::fun2(); error: 'fun2' is not a member of 'A' 
    fun3(); // works ok 
} 

Nasıl erişmek için fonksiyon FUN2()? Eğer fun arayabilir

+6

+1: İyi formüle edilmiş soru. –

+0

Boost'un akıllı işaretçisinde bu tür bir kodu görüyoruz: intrusive_ptr, bu bana ne olması gerektiğini ilk yapmamı sağladı. Benim için bu şekilde tanımlamak, kapsam içinde bir arkadaş tanımlamak ve sınıf kapsamı beyanında arkadaş olarak prototip olarak işaretlemek daha mantıklı değil.Genel ad alanında – Gabriel

cevap

34
class A{ 

public: 
    friend void fun(A a){std::cout << "Im here" << std::endl;} 
    friend void fun2(){ std::cout << "Im here2" << std::endl; } 
    friend void fun3(); 
}; 

, yine aynı işlevin bir deklarasyon eksik küresel kapsamda kendisi.

Bu kapsamda hiçbir kodun fun2'un bulunmadığı konusunda hiçbir fikri olmadığı anlamına gelir.

fun için aynı sorun oluşur; aksi halde Argümana Bağımlı Arama işlevi ele geçirebilir ve işlevi bulabilir, çünkü A türünde bir argüman vardır.

yerine her zamanki gibi Fonksiyonlarınızı tanımlayan öneririz:

class A { 
    friend void fun(A a); 
    friend void fun2(); 
    friend void fun3(); 
}; 

void fun(A a) { std::cout << "I'm here" << std::endl; } 
void fun2() { std::cout << "I'm here2" << std::endl; } 
void fun3(); 

Bildirimi artık everything works (bunu tanımlı çünkü hiç fun3 hariç).

21

nedeni sınıfına A içindeki arkadaşı beyan argümanı bağımlı arama sadece aracılığıyla görünür kılıyor. Aksi halde, arkadaş beyannameleri, görünecekleri sınıf kapsamı dışında otomatik olarak göründüklerini beyan ettikleri işlevleri yapmazlar.

main içinde fun2 görünmesini sağlamak için ad alanı kapsamına veya main içine bir bildirim eklemeniz gerekir.

E.g. (Sınıfının dışında) tanımı main dan görünür hale getiren bir bildiri de olduğu

void fun2(); 

fun3main içinde görülebilir.

ISO/IEC 14882: 2011 7.3.1.2:

arkadaşının adı niteliksiz arama (3.4.1) veya bir eşleştirme beyanı olana kadar nitelikli arama (3.4.3) ile bulunmazsa

Bu isim alanı kapsamında sağlanmıştır (arkadaşlık veren sınıf tanımından önce veya sonra).

3.4.2 (değişken bağımlı ad arama)/4:

Herhangi arkadaş işlevleri veya ilişkili sınıfların beyan arkadaşı fonksiyon şablonları onlar olmasa bile kendi ad dahilinde görünür olan ad-scope sıradan bir arama sırasında görülebilir (11.3). fun2tanımın aynı anda A bir friend yerine bir üyesinden daha "global" bir işlevi tanımlayın ve ona yapar rağmen

+0

beyanı sorunu çözer, ancak ana fonksiyona yerleştirmek bağlayıcı hata üretir. Teşekkürler. – scdmb

+0

@scdmb: Bağlayıcı hatası hakkında şaşırdım, geçerli olmalı. –

+0

Hayır, _definition-declaration_ öğesinin "main" içine yerleştirilmesi [_compiler_ hatasına neden olur] (http://codepad.org/KrhX3kHL). [Charles'ın önerdiği doğru] (http://codepad.org/ERZrmowu). Ve bir dahaki sefere, bir hata raporu ile geri döndüğünüzde lütfen bir test çantası verin. Beyanname ve tanım arasındaki fark için C++ kitabınıza bakın. –