2012-06-04 143 views
0

我有以下代碼結構(ResourceParameter是空班):如何爲模板類調用非默認構造函數?

Solver.cpp

#include "Solver.h" 
#include "ValueFunction.h" 

using namespace std; 

template<typename T> 
Solver<T>::Solver(vector<vector<Resource> >& resources, const Parameter& params) : 
    states(resources.size()) { 
    for (int i=0; i<resources.size(); i++) { 
     states[i] = State<T>(resources[i], params); 
    } 
} 

// Explicit class declaration 
template class Solver<ValueFunction>; 

Solver.h

#ifndef SOLVER_H_ 
#define SOLVER_H_ 

#include <vector> 
#include "Resource.h" 
#include "Parameter.h" 
#include "State.h" 

template<typename T> 
class Solver { 
    public: 
     Solver(
      std::vector<std::vector<Resource> >& resources, 
      const Parameter& params 
     ); 
    private: 
     std::vector<State<T> > states; 
}; 

#endif /* SOLVER_H_ */ 

State.cpp

#include "State.h" 
#include "ValueFunction.h" 

using namespace std; 

template<typename T> 
State<T>::State(vector<Resource>& _resources, const Parameter& params) : 
resources(_resources), valfuncs(_resources.size(), T(params)) { 
} 

template class State<ValueFunction>; 

State.h

#ifndef STATE_H_ 
#define STATE_H_ 

#include <vector> 
#include "Parameter.h" 
#include "Resource.h" 

template<typename T> 
class State { 
public: 
    State() {}; 
    State(std::vector<Resource>& _resources, const Parameter& params); 
    ~State() {}; 
private: 
    std::vector<Resource> resources; 
    std::vector<T> valfuncs; 
}; 

#endif /* STATE_H_ */ 

ValueFunction.cpp

#include "ValueFunction.h" 

ValueFunction::ValueFunction(const Parameter& _params) : params(_params) { 
} 

ValueFunction.h

#ifndef VALUEFUNCTION_H_ 
#define VALUEFUNCTION_H_ 

#include "Parameter.h" 

class ValueFunction { 
public: 
    ValueFunction(const Parameter& _params); 
private: 
    const Parameter& params; 
}; 

#endif /* VALUEFUNCTION_H_ */ 

通過以下調用:

#include "Solver.h" 
#include "State.h" 
#include "ValueFunction.h" 
#include "Parameter.h" 

using namespace std; 

int main(int argc, char *argv[]) { 
Parameter params; 
    vector<vector<Resource> > resources(4); 
    Solver<ValueFunction> sol(resources, params); 
    return 0; 
} 

而且我得到以下錯誤:

Solver.cpp:18:16: instantiated from here 
ValueFunction.h:6:21: error: non-static reference member ‘const Parameter& ValueFunction::params’, can't use default assignment operator 

如何正確調用ValueFunction的非默認構造函數,或者是否有其他方式用非默認構造函數(傳遞常量引用)初始化std::vector

更新

的誤差在此post解釋。但是,我的問題的解決方法並不清楚。有什麼建議麼?

+0

錯誤的發生是因爲我想'初始化與類''ValueFunction' _params' params'(不知道爲什麼這會導致錯誤)。 – Reza

+2

您必須將模板類的定義放在頭文件中。模板定義需要在實例化處可見。在你的情況下,他們不是,所以你的編譯器很困惑。參見[這個問題](http://stackoverflow.com/questions/3749099/why-應該 - 實現 - 和 - 聲明 - 模板 - 類 - 在 - 在 - )。我把你的代碼放在一個源文件中並編譯。 – jrok

+0

@jrok它不是一個instatiation問題,據我所知隱式實例化被編譯器接受爲explicite(參見[here](http://www.cplusplus.com/forum/articles/14272/) )。 – Reza

回答

4

您正在使用構造函數的形式初始化states,Solver,該構造函數調用矢量成員的默認構造函數。您可以將第二個參數傳遞給類型爲State<T>states的矢量構造函數,並且該矢量將使用複製構造函數來初始化使用該參數作爲源的矢量元素。在構造函數Solver中的循環將繼續提供您在狀態向量中實際需要的值。

引用不能由編譯器生成的默認構造函數初始化。這是因爲默認構造函數的作用是初始化對象,但引用需要引用某些東西。就像您在聲明不帶初始值設定項的引用變量時出錯一樣,默認的構造函數也會遇到同樣的問題。

int &r;  // this is an error 
int i; 
int &rr = i; // this is proper 

使用矢量構造函數的拷貝構造函數可以幫助你避免這個問題,因爲拷貝構造函數初始化它被複制對象的值的參考。在這種初始化向量的形式中,states中的每個元素都被設置爲與第一個元素相同的值。

... 
    : states(resources.size(), State<T>(resources[0], params)) 
... 

也許是更好的方式去是用作載體本身默認的構造函數,並使用reservepush_back將元素添加到載體。這樣更好,因爲它避免了創建任何對象,直到它實際添加到向量中。

... 
    : states() 
... 
    states.reserve(resources.size()); 
    for (int i...) { 
     states.push_back(State<T>(resources[i], params)); 
    } 
... 

第三種方法,將那種讓你原來的代碼工作它是書面的方式是定義自己的默認構造函數ValueFunction初始化的params成員的東西(也許是可怕的全球)。

class ValueFunction { 
public: 
    ValueFunction(); // define our own default constructor 
    ... 
}; 

const Parameter global_default_parameter; 

ValueFunction::ValueFunction() : params(default_parameter) {} 
+0

有沒有辦法將整個向量的資源傳遞給構造函數?舉例來說,向量'states'的第一個'State'應該用'resources [0]'初始化,第二個用'resources [1]'等等? – Reza

+0

@Reza,這會浪費精力,因爲你必須編寫一個輔助函數來創建整個向量,然後在'states'上調用向量的拷貝構造函數,這會導致向量被重新創建。 – jxh

+0

你的答案有助於解決我的問題的一部分(正確使用'State'構造函數),但它無法爲常量成員上調用'std :: vector'調用複製構造函數的問題提供解決方案。因此,你的第二種方法不能解決我的問題。我的解決方法是儘管類似,你在最後一部分提出,但不要再使用'const Parameter&'。 – Reza