關於C++中的前置宣告
阿新 • • 發佈:2018-12-05
在編寫C++程式的時候,偶爾需要用到前置宣告(Forward declaration)。下面的程式中,帶註釋的那行就是類B的前置說明。這是必須的,因為類A中用到了類B,而類B的宣告出現在類A的後面。如果沒有類B的前置說明,下面的程式將不同通過編譯,編譯器將會給出類似“缺少型別說明符”這樣的出錯提示。
程式碼一:
// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B; // 這是前置宣告(Forward declaration)
class A
{
private :
B* b;
public:
A(B* b):b(b)
{
}
…
};
class B
{
…
};
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
B* b = new B();
A* a = new A(b);
delete a;
delete b;
return 0;
}
上面程式可以順利編譯和執行(幾乎沒有做什麼,也沒有輸出)。
是不是有了前置說明就萬事大吉了呢?我們看看下面的程式碼(帶陰影部分的程式碼是新增加的):
程式碼二:
// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B; // 這是前置宣告(Forward declaration)
class A
{
private:
B* b;
public:
A(B* b):b(b)
{
}
void someMethod()
{
b->someMethod(); // (1)
}
};
class B
{
private:
public:
void someMethod()
{
cout << "something happened..." << endl;
}
};
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
B* b = new B();
A* a = new A(b);
a->someMethod();
delete a;
delete b;
return 0;
}
一編譯,發現程式碼(1)處出錯。出錯提示往往包括(不同的編譯器給出的提示會有所不同):
1. 使用了未定義的型別B;
2. “->somemethod”的左邊必須指向類/結構/聯合/泛型型別
原因:
1. (1)處使用了型別B的定義,因為呼叫了類B中的一個成員函式。前置宣告class B;僅僅聲明瞭有一個B這樣的型別,而並沒有給出相關的定義,類B的相關定義,是在類A後面出現的,因此出現了編譯錯誤;
2. 程式碼一之所以能夠通過編譯,是因為其中僅僅用到B這個型別,並沒有用到類B的定義。
解決辦法是什麼?
將類的宣告和類的實現(即類的定義)分離。如下所示:
// ForwardDeclaration.h 類的宣告
#include <iostream>
using namespace std;
class B; // 這是前置宣告(Forward declaration)
class A
{
private:
B* b;
public:
A(B* b);
void someMethod();
};
class B
{
private:
public:
void someMethod();
};
// ForwardDeclaration.cpp 類的實現
#include "ForwardDeclaration.h"
A::A(B* b):b(b)
{
}
void A::someMethod()
{
b->someMethod();
}
void B::someMethod()
{
cout << "something happened..." << endl;
}
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
B* b = new B();
A* a = new A(b);
a->someMethod();
delete a;
delete b;
return 0;
}
結論:
前置宣告只能作為指標或引用,不能定義類的物件,自然也就不能呼叫物件中的方法了。
而且需要注意,如果將類A的成員變數B* b;改寫成B& b;的話,必須要將b在A類的建構函式中,採用初始化列表的方式初始化,否則也會出錯。關於這點,詳見:特殊資料型別成員變數的初始化
轉自:http://patmusing.blog.163.com/blog/static/135834960201038113714199/