C++小例子——04 列向量模板类ColVector

本文介绍了如何将C++的列向量类改造成模板类,允许元素类型多样化,如vector和tensor。通过在头文件中声明模板类的实例化,实现了头文件和cpp文件的分离编译。提供了ColVector.h、ColVector.cpp和main.cpp的代码示例,并通过测试验证了所有功能的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

把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;
}

测试结果,表明所有函数均实现了其功能。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值