friend etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
friend etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

7 Ağustos 2020 Cuma

friend Anahtar Kelimesi - C++ Function

Giriş
Friend Function, bir sınıfın metodu olmadığı halde o sınıfın private alanlarına erişebilir. Gerekirse "friend function signature" sınıfa forward decleration ile tanıtılmalıdır.

Friend Function Tanımlama İçin 3 Yöntem Var
1. Declaration ve Definition Sınıf Dışında
2. Declaration ve Definition Sınıf Dışında. Her ikisi de inline modifier kullanır
3. Declaration sınıf dışında Definition Sınıf İçinde

En azından declaration her zaman sınıf dışınd olmalı ki Argument Dependent Lookup (ADL) yapılabilsin.

Örnek - Tanımlama
friend function tanımlamal için Şöyle yaparız.
class Box
{
  int width;
public :
  Box()
  {
    width =20;
  }
    
  friend void printWidth(Box b);
};

void printWidth(Box b)
{
  cout<< "Width is "<<b.width;
}
Örnek - Tanımlama
Şöyle yaparız.
class Point
{
private:
  int x;
public:
  Point(int X) : x(X) {}

  friend bool operator==(Point cP1, Point cP2);
};

bool operator==(Point cP1, Point cP2)
{
  return (cP1.x == cP2.x);
}
Örnek - Tanımlama (Definition Sınıf İçinde)
Şöyle yaparız. friend metodun gerçekleştirimi sınıfın dışında değil, sınıfın içindedir yani inline'dır. Ancak yine de friend metodun imzasını sınıfın ADL için dışına yazmak gerekir.
class X {
  public:
    friend bool operator==(int, X const &) { /* ... */ }
};

bool operator==(int, X const &);
Örnek - Argument Gerekir
Şöyle yaparız.
using namespace std;

template <typename T>
class C
{
  public:
    friend void f() { cout << "f"<<endl;}
    friend void f(C<T> const &) {cout << "f tmepltae" <<endl; }
};

C<int> c;

void g(C<int>* p)
{
  f();   //Derlenmez!
  f(*p); //Derlenir
}
Not : Eğer sınıfımız template ise metodu dışarı almak için friend metodun da template olması gerekir.

Örnek - Argument Gerekir
Friend Function'ı çağırmak için ADL kullanılır. Şöyle yaparız.
struct S
{
  friend void f() {}
  friend void g(S const&) {}
} const s;

int main()
{
  // f();     // error: 'f' was not declared in this scope
  // S::f();  // error: 'f' is not a member of 'S'
  g(s);
  // S::g(s); // error: 'g' is not a member of 'S'
}
Örnek - Conversion Operator
Şöyle yaparız. Burada hem A hem de B için operator << çağrılır çünkü aralarında kalıtım ilişkisi olmadığı halde B sınıfının A'ya conversion operator metodu vardır.
class A {
public:
  friend inline std::ostream& operator<<(std::ostream& os, const A&);
};

inline std::ostream& operator<<(std::ostream& os, const A&) {
  os << "Called\n";
  return os;
}

class B {
public:
  operator A() { return A(); }
};

int main()
{
  A a;
  std::cout << a;
  B b;
  std::cout << b;
}
Eğer elimizdeki kodu şöyle yaparsak derlenmez. Hata olarak " no suitable function for operator<< is found for b" alırız. Çünkü friend function için ADL kullanılır ve main metodu A içindeki friend fuction'i göremez.
class A {
public:
  friend std::ostream& operator<<(std::ostream& os, const A&) {
    os << "Called\n";
    return os;
  }
};

class B {
public:
  operator A() { return A(); }
};

int main()
{
  A a;
  std::cout << a;
  B b;
  std::cout << b;
}
Düzeltmek için şöyle yaparız. Burada frien metodun kendisi (definition) sınıf içinde olsa bile declaration görülebildiği için ADL yapılabilir.
class A {
public:
  friend std::ostream& operator<<(std::ostream& os, const A&) {
    os << "Called\n";
    return os;
  }
};

std::ostream& operator<<(std::ostream& os, const A&);

class B {
public:
  operator A() { return A(); }
};

int main()
{
  A a;
  std::cout << a;
  B b;
  std::cout << b;
}

3 Eylül 2018 Pazartesi

friend Anahtar Kelimesi - Class

Örnek
Bu örnekte B sınıfı, A sınıfının private olan alanlarına erişebilir. friend'in A sınıfı içinde public, protected bir alanda tanımlanması önemli değildir.
class A
{
  int member;
  friend /*class*/ B;  // class is optional, required if B isn't declared yet
};
B sınıfı şöyledir.
class B
{
  A& a_ref;
  void manipulate()
  {
    a_ref.member++;
  }
};
Örnek
Şöyle yaparız.
struct X {
  friend class Y;
  class Y* ptr;
};

Namespace örneği
Başka bir namespace içindeki B sınıfı friend yapılmak istenirse önce forward friend class declaration yapılması gerekir. Örnek:
namespace NamespaceB {
    class ClassB;
};

namespace NamespaceA {
    class ClassA {
          friend class NamespaceB::ClassB;
     //Other methods...
   }
};

Friend Sınıfın Metodu
A sınıfının private alanlarına sadece B sınıfının destructor metodunda erişilsin istersek şöyle yaparız.
struct A
{
private:
  // some private stuff
  friend B::~B();
};
Template Class örneği
Template class içinde friend ilan edilen sınıf template olamaz. Yani template sınıfım içinde partial speciliazation yapamıyorum.
Friend declarations shall not declare partial specializations. 
template<class T> class A { };
class X {
  template<class T> friend class A<T*>; // error
};
Eğer template sınıfım içinde friend ilan ettiğim sınıf template değilse sorun yok.
template <class, class> friend class Element;        // OK

template <class, class> friend class Element<T, T>;  // Error