Giriş
Derleyici sınıflara eriştiği zaman, sınıfın "complete type" olmasını ister.
Örnek - metodun bulunamaması
Bu örneği sadece C++'ın C'ye göre çok daha sıkı kurallara sahip olduğunu göstermek için aldım. Yoksa örnekte class değil, metod bulunamıyor.
Derleyici sınıflara eriştiği zaman, sınıfın "complete type" olmasını ister.
Örnek - metodun bulunamaması
Bu örneği sadece C++'ın C'ye göre çok daha sıkı kurallara sahip olduğunu göstermek için aldım. Yoksa örnekte class değil, metod bulunamıyor.
C90 ile "imlicit function decleration" özelliği vardı ve aşağıdaki kod derlenirdi. Ancak bu özellik C99 ile kaldırıldı. C++ ise C99'dan daha da sıkı kurallara sahip.
Aşağıdaki örnekte sum() metodu scope içinde olmadığı için derleme hatası alırız.
Bu bir C++ örneği. Aşağıdaki örnekte student "complete type" olmadığı için derleme hatası alırız.
Yukarıdaki örnekler aslında çok büyük dert değil, çünkü kodda eksik bir şey yok, sadece kodun sırası biraz karışık. Bu durumda derleyiciye yardımcı olmak için "Forward Declaration" yapmak gerekiyor. Yani derleyiciye, sen bu kod parçasını şimdi görmedin ancak ileride göreceksin çalışmaya devam et diyoruz.
Aşağıdaki örnekte sum() metodu scope içinde olmadığı için derleme hatası alırız.
#include<stdio.h>
int main()
{
int a=sum(4,6);
printf("%d",a);
return 0;
}
int sum(int a,int b)
{
return a+b;
}
Hata şöyledir.‘sum’ was not declared in this scope
Örnek - sınıfın bulunamamasıBu bir C++ örneği. Aşağıdaki örnekte student "complete type" olmadığı için derleme hatası alırız.
#include<iostream.h>
#include<conio.h>
void main()
{
student s;
s.show();
getch();
}
class student
{
int age;
public:
void show();
};
void student::show()
{
age = 5;
cout << age;
}
Forward DeclarationYukarıdaki örnekler aslında çok büyük dert değil, çünkü kodda eksik bir şey yok, sadece kodun sırası biraz karışık. Bu durumda derleyiciye yardımcı olmak için "Forward Declaration" yapmak gerekiyor. Yani derleyiciye, sen bu kod parçasını şimdi görmedin ancak ileride göreceksin çalışmaya devam et diyoruz.
Bu durumda derleyici sınıfın tipi, büyüklüğü, üyeleri hakkında hiçbir şey bilmez. Yani sınıf bir "incomplete type" olarak kabul edilir. Ve Incomplete Type ile yine de çalışmak mümkün.
Forward Declaration vs Elaborated Type Specifier
Forward Declaration aslında Elaborated Type Specifier kullanımının özel bir halinin ismidir. Sadece class ile ilgilenen 3. maddesine değinir.
Ne Yapılabilir
Incomplete Type'ı X olarak kabul edersek ve elimizde şöyle bir forward declaration varsa. Burada baştaki class kelimesine dikkat!
class X;
1. Member TanımlanabilirŞöyle yaparız.
class Foo {
X *pt;
X &pt;
};
2. Metod Declare EdilebilirŞöyle yaparız.
void f1(X);
X f2();
3. Pointer veya Reference Kullanan Metod Tanımlanabilir - Declare Değil, DefineŞöyle yaparız.
void f3(X*, X&) {}
X& f4() {}
X* f5() {}
Bir başka örnekclass MyClass;
class MyClass2: public MyBaseClass {
MyClass2 (MyClass& so);
};
Ne Yapılamaz
Incomplete Type'ı X olarak kabul edersek.
1. Kalıtım Yapılamaz
Şunu yapamayız.
class Foo : X {} // compiler error!
2. Üye TanımlanamazŞunu yapamayız.
class Foo {
X m; // compiler error!
};
Üye dizisi de tanımlanamaz.class Foo{
X myX[10];
};
3. Metod Tanımlanamaz - Declare edilme maddesinden farklı !Şunu yapamayız.
void f1(X x) {} // compiler error!
X f2() {} // compiler error!
Aradaki fark şöyle görülebilir.struct X; // Forward declaration of X
void f1(X* px) {} // Legal: can always use a pointer/reference
X f2(int); // Legal: return value in function prototype
void f3(X); // Legal: parameter in function prototype
void f4(X) {} // ILLEGAL: *definitions* require complete types
4. X'in Alan veya Metodlarını KullanamayızŞunu yapamayız.
class Foo {
X *m;
void method()
{
m->someMethod(); // compiler error!
int i = m->someField; // compiler error!
}
};
NamespaceAynı isim alanı içindeki iki sınıf forward declaration satırını da isim alanı içine koymalıdır. A sınıfı B sınıfını şöyle kullanır.
// A.h
namespace ns {
class B; // forward declare B
class A {
public:
// Some functions with B references as arguments
};
}
Cyclic DependencyŞöyle yaparız.
// A.h (Header guarded)
namespace ns {
class B; // forward declare B
class A {
public:
float a, b;
void aFunc(B &b);
};
}
// B.h (Header guarded)
namespace ns {
class A; // forward declare A
class B {
public:
void bFunc(A &a);
int getRand();
};
}
// A.cpp
#include "A.h"
#include "B.h"
namespace ns {
void A::aFunc(B& b) { /* ... */ }
}
// B.cpp
#include "A.h"
#include "B.h"
namespace ns {
void B::bFunc(A& b) { /* ... */ }
int B::getRand() { /* ... */ }
}
Hiç yorum yok:
Yorum Gönder