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;
}

Hiç yorum yok:

Yorum Gönder