把03列向量类改成了模板类,如此一来,列向量的元素类型不再局限于double,而可以是vector,tensor等。对于模板类而言,要想实现头文件和cpp文件的分开编译处理,头文件中需要对模板类进行实例化的声明。
写好的代码如下:
ColVector.h头文件
// 2020-07-30
// class ColVector -- head file
// A column vector template class
// type could be double, vector, tensor, etc
// Author: Guanhua Mei
#ifndef ColVector_H
#define ColVector_H
#include <iostream>
#include "Vector.h"
template<class T>
class ColVector
{
private:
unsigned int m_nSize; // capicity of column vector, number of elems
T* m_pColVct; // column vector array pointer
public:
// constructors
// construct with size and value
ColVector(unsigned int = 0, T = T());
// copy constructor, deep copy
ColVector(const ColVector<T>&);
// copy assignment, deep copy
ColVector& operator=(const ColVector<T>&);
// move constructor, shallow copy
ColVector(ColVector<T>&&) noexcept;
// move assignment, shallow copy
ColVector& operator=(ColVector<T>&&) noexcept;
// destructor
~ColVector();
// return size
unsigned int size() const { return m_nSize; }
// get value at idx
T getCompIdx(unsigned int) const;
// set value at idx
void setCompIdx(unsigned int, const T& = T());
// set all
void setAll(const T& = T());
// operator [] to fetch value
T& operator[](unsigned int);
const T& operator[](unsigned int) const;
// operator += -= *= /=, legality wil not be checked!!
ColVector& operator+=(const ColVector&);
ColVector& operator+=(const T&);
ColVector& operator-=(const ColVector&);
ColVector& operator-=(const T&);
ColVector& operator*=(const ColVector&);
ColVector& operator*=(const T&);
ColVector& operator/=(const ColVector&);
ColVector& operator/=(const T&);
// friend operator + - * /, legality wil not be checked!!
template<class Type>
friend ColVector<Type> operator+(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator+(const ColVector<Type>&, const Type&);
template<class Type>
friend ColVector<Type> operator+(const Type&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator-(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator-(const ColVector<Type>&, const Type&);
template<class Type>
friend ColVector<Type> operator-(const Type&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator*(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator*(const ColVector<Type>&, const Type&);
template<class Type>
friend ColVector<Type> operator*(const Type&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator/(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
friend ColVector<Type> operator/(const ColVector<Type>&, const Type&);
template<class Type>
friend ColVector<Type> operator/(const Type&, const ColVector<Type>&);
// print
void print();
// outputstream operator <<
template<class Type>
friend std::ostream& operator<<(std::ostream&, const ColVector<Type>&);
};
// instantiation template class
template class ColVector<double>;
template class ColVector<Vector>;
// instantiation template friend functions
// instantiation of operator <<
template std::ostream& operator<<(std::ostream&, const ColVector<double>&);
template std::ostream& operator<<(std::ostream&, const ColVector<Vector>&);
// friend functions need to be declarated outside again!
// friend function of outputstream operator <<
template<class T>
std::ostream& operator<<(std::ostream&, const ColVector<T>&);
// friend functions of operator + - * /, legality wil not be checked!!
template<class Type>
ColVector<Type> operator+(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator+(const ColVector<Type>&, const Type&);
template<class Type>
ColVector<Type> operator+(const Type&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator-(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator-(const ColVector<Type>&, const Type&);
template<class Type>
ColVector<Type> operator-(const Type&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator*(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator*(const ColVector<Type>&, const Type&);
template<class Type>
ColVector<Type> operator*(const Type&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator/(const ColVector<Type>&, const ColVector<Type>&);
template<class Type>
ColVector<Type> operator/(const ColVector<Type>&, const Type&);
template<class Type>
ColVector<Type> operator/(const Type&, const ColVector<Type>&);
// instantiation of operator + - * /
template ColVector<double> operator+(const ColVector<double>&, const ColVector<double>&);
template ColVector<double> operator+(const ColVector<double>&, const double&);
template ColVector<double> operator+(const double&, const ColVector<double>&);
template ColVector<double> operator-(const ColVector<double>&, const ColVector<double>&);
template ColVector<double> operator-(const ColVector<double>&, const double&);
template ColVector<double> operator-(const double&, const ColVector<double>&);
template ColVector<double> operator*(const ColVector<double>&, const ColVector<double>&);
template ColVector<double> operator*(const ColVector<double>&, const double&);
template ColVector<double> operator*(const double&, const ColVector<double>&);
template ColVector<double> operator/(const ColVector<double>&, const ColVector<double>&);
template ColVector<double> operator/(const ColVector<double>&, const double&);
template ColVector<double> operator/(const double&, const ColVector<double>&);
template ColVector<Vector> operator+(const ColVector<Vector>&, const ColVector<Vector>&);
template ColVector<Vector> operator+(const ColVector<Vector>&, const Vector&);
template ColVector<Vector> operator+(const Vector&, const ColVector<Vector>&);
template ColVector<Vector> operator-(const ColVector<Vector>&, const ColVector<Vector>&);
template ColVector<Vector> operator-(const ColVector<Vector>&, const Vector&);
template ColVector<Vector> operator-(const Vector&, const ColVector<Vector>&);
template ColVector<Vector> operator*(const ColVector<Vector>&, const ColVector<Vector>&);
template ColVector<Vector> operator*(const ColVector<Vector>&, const Vector&);
template ColVector<Vector> operator*(const Vector&, const ColVector<Vector>&);
template ColVector<Vector> operator/(const ColVector<Vector>&, const ColVector<Vector>&);
template ColVector<Vector> operator/(const ColVector<Vector>&, const Vector&);
template ColVector<Vector> operator/(const Vector&, const ColVector<Vector>&);
// dot product, legality wil not be checked!!
double dotProduct(const ColVector<double>&, const ColVector<double>&);
// magnitude, i.e., 2nd norm
double norm(const ColVector<double>&);
// unit
ColVector<double> unit(const ColVector<double>&);
#endif
ColVector.cpp文件
// 2020-07-30
// class ColVector -- cpp file
#include "ColVector.h"
// constructors
// construct with size and value
template<class T>
ColVector<T>::ColVector(unsigned int nSize, T tVal) :
m_nSize(nSize), m_pColVct(nullptr)
{
//std::cout << "Construct by size and value. " << std::endl;
if (m_nSize > 0) // ask memory
m_pColVct = new T[m_nSize];
for (unsigned int i = 0; i < m_nSize; ++i) // assign values
m_pColVct[i] = tVal;
}
// copy constructor, deep copy
template<class T>
ColVector<T>::ColVector(const ColVector<T>& colVct)
{
//std::cout << "Copy constructor. " << std::endl;
m_nSize = colVct.m_nSize;
m_pColVct = nullptr;
if (m_nSize > 0) // ask memory
m_pColVct = new T[m_nSize];
for (unsigned int i = 0; i < m_nSize; ++i) // assign values
m_pColVct[i] = colVct.m_pColVct[i];
}
// copy assignment, deep copy
template<class T>
ColVector<T>& ColVector<T>::operator=(const ColVector<T>& colVct)
{
//std::cout << "Copy assignment. " << std::endl;
if (this == &colVct)
return *this;
if (m_pColVct != nullptr) // free old memory
delete[] m_pColVct;
m_pColVct = nullptr;
m_nSize = colVct.m_nSize;
if (m_nSize > 0) // ask new memory
m_pColVct = new T[m_nSize];
for (unsigned i = 0; i < m_nSize; ++i) // assign values
m_pColVct[i] = colVct.m_pColVct[i];
return *this;
}
// move constructor, shallow copy while keep memory
template<class T>
ColVector<T>::ColVector(ColVector<T>&& colVctRhs) noexcept:
m_nSize(colVctRhs.m_nSize), m_pColVct(colVctRhs.m_pColVct)
{
//std::cout << "move constructor" << std::endl;
colVctRhs.m_nSize = 0;
// Set rhs value ptr to nullptr, to keep its memory in destructor
colVctRhs.m_pColVct = nullptr;
}
// move assignment, shallow copy while keep memory
template<class T>
ColVector<T>& ColVector<T>::operator=(ColVector<T>&& colVctRhs) noexcept
{
//std::cout << "move assignment. " << std::endl;
if (this == &colVctRhs) // prevent self assignment
return *this;
// free old memory
m_nSize = 0;
if (m_pColVct != nullptr)
delete[] m_pColVct;
// assign size and pointer
m_nSize = colVctRhs.m_nSize;
m_pColVct = colVctRhs.m_pColVct;
// set rhs ptr null to keep memory in destructor
colVctRhs.m_nSize = 0;
colVctRhs.m_pColVct = nullptr;
return *this;
}
// destructor
template<class T>
ColVector<T>::~ColVector()
{
//std::cout << "Destructor. " << *this << std::endl;
if (m_pColVct != nullptr) // free memory
delete[] m_pColVct;
m_pColVct = nullptr;
m_nSize = 0;
}
// get value at idx
template<class T>
T ColVector<T>::getCompIdx(unsigned int nIdx) const
{
if (nIdx < m_nSize)
return m_pColVct[nIdx];
else
return T();
}
// set value at idx
template<class T>
void ColVector<T>::setCompIdx(unsigned int nIdx, const T& tVal)
{
if (nIdx < m_nSize)
m_pColVct[nIdx] = tVal;
}
// set all
template<class T>
void ColVector<T>::setAll(const T& tVal)
{
for (unsigned i = 0; i < m_nSize; ++i)
m_pColVct[i] = tVal;
}
// operator [] to fetch value
template<class T>
T& ColVector<T>::operator[](unsigned int nIdx)
{
return m_pColVct[nIdx]; // do not check if nIdx is correct
}
template<class T>
const T& ColVector<T>::operator[](unsigned int nIdx) const
{
return m_pColVct[nIdx]; // do not check if nIdx is correct
}
// operator += -= *= /=, legality wil not be checked!!
template<class T>
ColVector<T>& ColVector<T>::operator+=(const ColVector<T>& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] += colVct.m_pColVct[i];
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator+=(const T& tVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] += tVal;
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator-=(const ColVector<T>& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] -= colVct.m_pColVct[i];
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator-=(const T& tVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] -= tVal;
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator*=(const ColVector<T>& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] *= colVct.m_pColVct[i];
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator*=(const T& tVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] *= tVal;
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator/=(const ColVector<T>& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] /= colVct.m_pColVct[i];
return *this;
}
template<class T>
ColVector<T>& ColVector<T>::operator/=(const T& tVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pColVct[i] /= tVal;
return *this;
}
// functions of operator + - * /, legality wil not be checked!!
template<class Type>
ColVector<Type> operator+(const ColVector<Type>& lhs, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp = lhs;
colVctTmp += rhs;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator+(const ColVector<Type>& lhs, const Type& tVal)
{
ColVector<Type> colVctTmp(lhs);
colVctTmp += tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator+(const Type& tVal, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp(rhs);
colVctTmp += tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator-(const ColVector<Type>& lhs, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp = lhs;
colVctTmp -= rhs;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator-(const ColVector<Type>& lhs, const Type& tVal)
{
ColVector<Type> colVctTmp(lhs);
colVctTmp -= tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator-(const Type& tVal, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp(rhs.m_nSize, tVal);
colVctTmp -= rhs;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator*(const ColVector<Type>& lhs, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp = lhs;
colVctTmp *= rhs;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator*(const ColVector<Type>& lhs, const Type& tVal)
{
ColVector<Type> colVctTmp(lhs);
colVctTmp *= tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator*(const Type& tVal, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp(rhs);
colVctTmp *= tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator/(const ColVector<Type>& lhs, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp = lhs;
colVctTmp /= rhs;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator/(const ColVector<Type>& lhs, const Type& tVal)
{
ColVector<Type> colVctTmp(lhs);
colVctTmp /= tVal;
return colVctTmp;
}
template<class Type>
ColVector<Type> operator/(const Type& tVal, const ColVector<Type>& rhs)
{
ColVector<Type> colVctTmp(rhs.m_nSize, tVal);
colVctTmp /= rhs;
return colVctTmp;
}
// print
template<class T>
void ColVector<T>::print()
{
if (m_nSize == 0)
std::cout << "Empty Column Vector! " << std::endl;
else
{
std::cout << "[";
for (unsigned int i = 0; i < m_nSize - 1; ++i)
std::cout << m_pColVct[i] << "; ";
std::cout << m_pColVct[m_nSize - 1] << "]" << std::endl;
}
}
// outputstream operator <<
template<class T>
std::ostream& operator<<(std::ostream& os, const ColVector<T>& colVct)
{
if (colVct.size() == 0)
os << "Empty Column Vector! ";
else
{
os << "[";
for (unsigned int i = 0; i < colVct.size() - 1; ++i)
os << colVct[i] << "; ";
os << colVct[colVct.size() - 1] << "]";
}
return os;
}
// dot product, legality wil not be checked!!
double dotProduct(const ColVector<double>& lhs,
const ColVector<double>& rhs)
{
double dVal = 0.0;
for (unsigned int i = 0; i < lhs.size(); ++i)
dVal += (lhs[i] * rhs[i]);
return dVal;
}
// magnitude, i.e., 2nd norm
double norm(const ColVector<double>& colVct)
{
return sqrt(dotProduct(colVct, colVct));
}
// unit
ColVector<double> unit(const ColVector<double>& colVct)
{
return (colVct / norm(colVct));
}
测试主函数main.cpp
// 2020-07-30
// Test of colVector template
// Author: Guanhua Mei
#include <iostream>
#include "ColVector.h"
#include "Vector.h"
int main()
{
ColVector<double> colVct2(5, 1.2);
ColVector<double> colVct1(colVct2);
std::cout << colVct1 << std::endl;
colVct1.setAll(2.3);
std::cout << colVct1 << std::endl;
colVct1.setCompIdx(0, 5.4);
colVct1.setCompIdx(1, 3.2);
std::cout << colVct1 << std::endl;
std::cout << colVct1.getCompIdx(1) << std::endl;
std::cout << colVct1[0] << std::endl;
std::cout << "-------------------------------------" << std::endl;
std::cout << "-------- test A += -= *= /= B -------" << std::endl;
colVct1 += colVct2;
colVct1.print();
colVct1 += 3;
colVct1.print();
colVct1 -= 3;
colVct1.print();
colVct1 -= colVct2;
colVct1.print();
colVct1 *= 3;
colVct1.print();
colVct1 *= colVct2;
colVct1.print();
colVct1 /= colVct2;
colVct1.print();
colVct1 /= 3;
colVct1.print();
std::cout << "-------------------------------------" << std::endl;
std::cout << "---------- test A + - * / B ---------" << std::endl;
std::cout << colVct1 + colVct2 << std::endl;
std::cout << colVct1 + 10.0 << std::endl;
std::cout << 10.0 + colVct1 << std::endl;
std::cout << colVct1 - colVct2 << std::endl;
std::cout << colVct1 - 10.0 << std::endl;
std::cout << 10.0 - colVct1 << std::endl;
std::cout << colVct1 * colVct2 << std::endl;
std::cout << colVct1 * 10.0 << std::endl;
std::cout << 10.0 * colVct1 << std::endl;
std::cout << colVct1 / colVct2 << std::endl;
std::cout << colVct1 / 10.0 << std::endl;
std::cout << 10.0 / colVct1 << std::endl;
std::cout << "-------------------------------------" << std::endl;
std::cout << "-------- test dot, norm, unit -------" << std::endl;
std::cout << dotProduct(colVct1, colVct2) << std::endl;
//std::cout << (5.4+3.2+2.3+2.3+2.3)*1.2 << std::endl;
std::cout << norm(colVct1) << std::endl;
std::cout << unit(colVct1) << std::endl;
// Correct!!
std::cout << "-------------------------------------" << std::endl;
std::cout << "----- test of colVector<Vector> -----" << std::endl;
ColVector<Vector> colVct3(3, Vector(1, 2, 3));
std::cout << colVct3 << std::endl;
ColVector<Vector> colVct4(colVct3);
std::cout << colVct4 << std::endl;
colVct3.setCompIdx(1, Vector(6, 7, 8)); colVct3.print();
colVct3.setAll(); colVct3.print();
colVct3.setCompIdx(0, Vector(1, 2, 3));
colVct3.setCompIdx(1, Vector(4, 5, 6));
colVct3.setCompIdx(2, Vector(7, 8, 9));
colVct3.print();
colVct4.setCompIdx(0, Vector(3, 1, 4));
colVct4.setCompIdx(1, Vector(1, 5, 9));
colVct4.setCompIdx(2, Vector(2, 6, 5));
colVct4.print();
colVct3 += colVct3; colVct3.print();
colVct3 += Vector(3, 4, 5); colVct3.print();
colVct3 -= Vector(3, 4, 5); colVct3.print();
colVct3 -= colVct4; colVct3.print();
colVct3 *= Vector(3, 4, 5); colVct3.print();
colVct3 *= colVct4; colVct3.print();
colVct3 /= Vector(3, 4, 5); colVct3.print();
colVct3 /= colVct4; colVct3.print();
std::cout << colVct3 + colVct4 << std::endl;
std::cout << colVct3 + Vector(1, 2, 3) << std::endl;
std::cout << colVct3 - colVct4 << std::endl;
std::cout << colVct3 - Vector(1, 2, 3) << std::endl;
std::cout << colVct3 * colVct4 << std::endl;
std::cout << colVct3 * Vector(1, 2, 3) << std::endl;
std::cout << colVct3 / colVct4 << std::endl;
std::cout << colVct3 / Vector(1, 2, 3) << std::endl;
return 0;
}
测试结果,表明所有函数均实现了其功能。