Mic*_*val 8 c++ constructor type-conversion copy-constructor
由于我的一些代码需要在不同类型的矩阵之间进行隐式转换(例如Matrix<int>to Matrix<double>),我定义了一个模板化的复制构造函数Matrix<T>::Matrix(Matrix<U> const&)而不是标准Matrix<T>::Matrix(Matrix<T> const&):
template <typename T> class Matrix {
public:
// ...
template <typename U> Matrix(Matrix<U> const&);
// ...
private
unsigned int m_rows, m_cols;
T *m_data;
// ...
};
Run Code Online (Sandbox Code Playgroud)
通过向复制构造函数添加适当的类型转换,此方法可以在不同类型的矩阵之间完美地转换.令人惊讶的是,在一个简单的复制构造函数可以运行的情况下,它会因malloc错误而失败:where U == T.果然,使用默认Matrix<T>::Matrix(Matrix<T> const&)签名重载复制构造函数可以解决问题.
这是一个糟糕的解决方案,因为它导致复制构造函数代码的批量复制(字面意思是未更改的复制和粘贴).更重要的是,我不明白为什么malloc没有重复代码会出现双重自由错误.此外,为什么template <typename T> template <typename U>这里需要极其冗长的语法而不是标准,而且更简洁template <typename T, typename U>?
模板化方法的完整源代码,在Mac OS 10.5上使用G ++ v4.0.1编译.
template <typename T> template <typename U> Matrix<T>::Matrix(Matrix<U> const& obj) {
m_rows = obj.GetNumRows();
m_cols = obj.GetNumCols();
m_data = new T[m_rows * m_cols];
for (unsigned int r = 0; r < m_rows; ++r) {
for (unsigned int c = 0; c < m_cols; ++c) {
m_data[m_rows * r + c] = static_cast<T>(obj(r, c));
}
}
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 13
它失败,因为模板不会抑制复制构造函数的隐式声明.它将作为一个简单的转换构造函数,当重载决策选择它时,它可用于复制对象.
现在,您可能在某处复制了矩阵,这将使用隐式定义的复制构造函数来执行平面复制.然后,复制的矩阵和副本将在它们的析构函数中删除相同的指针.
此外,为什么
template <typename T> template <typename U>需要非常详细的语法
因为涉及两个模板:Matrix,它是一个类模板,以及转换构造函数模板.每个模板都有自己的模板子句及其自己的参数.
<T>顺便说一句,你应该摆脱你的第一线.定义模板时不会出现这样的事情.
这是一个糟糕的解决方案,因为它会导致复制构造函数代码的批量重复
您可以定义一个成员函数模板,它将完成工作,并从转换构造函数和复制构造函数委托.这样,代码不会重复.
理查德在评论中提出了一个很好的观点,这使得我修改了我的答案.如果从模板生成的候选函数比隐式声明的复制构造函数更好地匹配,则模板"wins",并且将调用它.以下是两个常见示例:
struct A {
template<typename T>
A(T&) { std::cout << "A(T&)"; }
A() { }
};
int main() {
A a;
A b(a); // template wins:
// A<A>(A&) -- specialization
// A(A const&); -- implicit copy constructor
// (prefer less qualification)
A const a1;
A b1(a1); // implicit copy constructor wins:
// A(A const&) -- specialization
// A(A const&) -- implicit copy constructor
// (prefer non-template)
}
Run Code Online (Sandbox Code Playgroud)
如果任何成员具有,则复制构造函数也可以具有非const引用参数
struct B { B(B&) { } B() { } };
struct A {
template<typename T>
A(T&) { std::cout << "A(T&)"; }
A() { }
B b;
};
int main() {
A a;
A b(a); // implicit copy constructor wins:
// A<A>(A&) -- specialization
// A(A&); -- implicit copy constructor
// (prefer non-template)
A const a1;
A b1(a1); // template wins:
// A(A const&) -- specialization
// (implicit copy constructor not viable)
}
Run Code Online (Sandbox Code Playgroud)