模板類的建構函式呼叫錯誤問題分析
將當時錯誤的程式碼進行簡化後,程式碼如下:
程式碼1#include <iostream> #include <string> using namespace std; template<class T> class Test{ public: Test(const string& name) { this->m_name = name; } void Print() { cout << "name" << endl; } private: string m_name; T a; }; class Student { public: //Student():test("name"){} Test<int> test("name"); }; int main(int argc, char ** argv) { Student stu; return 0; }
以上程式碼暫且稱為程式碼1.
直接貼上當時提示的錯誤資訊為:
test.cpp:25: 錯誤:expected identifier before string constant
test.cpp:25: 錯誤:expected ‘,’ or ‘...’ before string constant
一個模板類,想要初始構建的時候,傳個引數進行,想到的當然是使用建構函式將name進行傳過去。而另一個類Student中使用了Test模板類。並在使用過程中,這樣傳入Test<int> test("name"),報出上述錯誤,當時一臉茫然,不知所措。
遇到問題,第一時間自己上網查了下資料,並自己再寫了個小示例,檢視這樣驗證是否OK,程式碼如下:
程式碼2#include <iostream> #include <string> using namespace std; template<class T> class Test{ public: Test(const string& name) { this->m_name = name; } void Print() { cout << "name" << endl; } private: string m_name; T a; }; int main(int argc, char ** argv) { Test<int> test("name"); return 0; }
以上程式碼稱為程式碼2,大家可以自己試一下,使用g++可以成功通過編繹生成可執行檔案。問題來了,為什麼程式碼1中使用Test<int> test("name")錯誤,而程式碼2中卻沒有問題呢?
解析:自己對於一些基礎概念沒有理解到位
1、程式碼1中,Student中使用Test的時候,是屬於類成員宣告。宣告階段,只是告訴編繹器,Student類中會有Test<int> test這個類成員,並沒有進行記憶體分配,那怎麼可能進行建構函式的呼叫?
2、程式碼2中,main函式中使用Test<int> test,表示的是類的定義。定義指的是真正為類的物件分配記憶體,並構建物件,故這裡使用Test<int> test("name")沒有問題。
3、如果程式碼1中,Student類需要使用Test<int> test並在構建的時候將引數傳進去得如何修改?可以在Student自身構建的時候,將test的構建函式引數傳進去。具體修改見下面程式碼3部分。
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Test{
public:
Test(const string& name) {
this->m_name = name;
}
void Print() {
cout << "name" << endl;
}
private:
string m_name;
T a;
};
class Student {
public:
Student():test("name"){}
Test<int> test;
};
int main(int argc, char ** argv) {
Student stu;
return 0;
}
總結:這個問題暴露自己在基礎概念的理解上還存在不足。一言以蔽之,就是“宣告”與“定義”的理解沒有到位。另外,就是這樣使用的場景用得少,之前沒有用過,多實踐,多發現問題,解決問題,才是成長之道。