再来一个列向量类colVector。
其成员变量有两个,元素数目,和用于动态申请释放内存空间的double型指针。
其构造函数可由元素数目和元素值(列向量中所有元素都是同一个值)来构造,也可用另外一个列向量来构造(拷贝构造,copy constructor),析构函数用来释放存储空间,此外,还有拷贝赋值(copy assignment)函数,即用操作符等号=来实现深拷贝赋值操作,以及移动构造(move constructor)函数,用右值来做浅复制(仅复制指针地址),和移动赋值(move constructor)函数,重载操作符等号=,用右值来做浅复制。
其他成员函数包括提取第idx个分量的值,设置第idx个分量的值,设置整体元素的值,用操作符中括号[]来获取第idx个分量的引用(可以给第idx个元素做修改)和常引用(只能把第idx个元素拿出来用,不能修改),以及复合运算符+=、-=、*=、/=,用于和另一个colVector或double型变量的自身加减乘除操作,友元运算符+、-、*、/用于列向量colVector和另一个列向量或标量double型之间的加减乘除运算。提供了计算两个列向量点积的操作函数,计算列向量二范数的函数,以及单位化列向量的函数,当然都是友元函数。最后,还重载了输入流操作符>>和输出流操作符<<用来读入和输出列向量。
当然,还可以在外面定义矩阵和列向量的相乘函数,以及线性求解器用于求解Ax=B。
列向量类colVector的框架如下:
成员变量
- 列向量的元素数目
- double指针用于动态申请释放内存空间,来存储列向量元素
成员函数
- 构造函数1,元素数目,元素值,缺省值为0
- 拷贝构造,由另一个列向量构造
- 拷贝赋值,重载赋值运算符=,左列向量 = 右列向量,将右列向量的值赋给左列向量
- 移动构造,由右值列向量构造
- 移动赋值,重载赋值运算符=,左列向量 = 右值列向量,将右值列向量的值浅复制给左列向量
- 析构函数,释放内存空间
- 提取第idx个元素的值getCompIdx
- 设置第idx个元素的值setCompIdx
- 设置所有元素的值setAll
- 返回第idx个元素的引用,重载operator[]实现
- 返回第idx个元素的常引用,重载operator[]实现
- 操作符+=:列向量+=列向量/double
- 操作符-=:列向量-=列向量/double
- 操作符*=:列向量*=列向量/double
- 操作符/=:列向量/=列向量/double
- 友元操作符+:列向量+列向量,列向量+double,double+列向量
- 友元操作符-:列向量-列向量,列向量-double,double-列向量
- 友元操作符*:列向量*列向量,列向量*double,double*列向量
- 友元操作符/:列向量/列向量,列向量/double,double/列向量
- 友元函数dotProduct,计算两个列向量的点积
- 友元函数norm,计算列向量的二范数(也称模或幅值)
- 友元函数unit,计算列向量的单位化列向量
- 友元输入符>>,读入列向量
- 友元输出符<<,输出列向量
写好的程序如下:
colVector.h 头文件
// 2020-07-09
// class colVector - head file
// A column vector class
// Author: Guanhua Mei
#ifndef colVector_H
#define colVector_H
#include <iostream>
class colVector
{
private:
unsigned int m_nSize; // capicity of column vector, number of elems
double* m_pdColVct; // column vector array double pointer
public:
// constructors
// construct with size and val
colVector(unsigned int = 0, double = 0.0);
// copy constructor, deep copy
colVector(const colVector&);
// copy assignment, deep copy
colVector& operator=(const colVector&);
// move constructor, shallow copy while keep memory
colVector(colVector&&) noexcept;
// move assignment, shallow copy while keep memory
colVector& operator=(colVector&&) noexcept;
// destructor
~colVector();
// get value at idx
double getCompIdx(unsigned int) const;
// set value at idx
void setCompIdx(unsigned int, double = 0.0);
// set all
void setAll(double = 0.0);
// operator [] to fetch value
double& operator[](unsigned int);
const double& operator[](unsigned int) const;
// operator += -= *= /=, legality wil not be checked!!
colVector& operator+=(const colVector&);
colVector& operator+=(const double&);
colVector& operator-=(const colVector&);
colVector& operator-=(const double&);
colVector& operator*=(const colVector&);
colVector& operator*=(const double&);
colVector& operator/=(const colVector&);
colVector& operator/=(const double&);
// friend operator + - * /, legality wil not be checked!!
friend colVector operator+(const colVector&, const colVector&);
friend colVector operator+(const colVector&, const double&);
friend colVector operator+(const double&, const colVector&);
friend colVector operator-(const colVector&, const colVector&);
friend colVector operator-(const colVector&, const double&);
friend colVector operator-(const double&, const colVector&);
friend colVector operator*(const colVector&, const colVector&);
friend colVector operator*(const colVector&, const double&);
friend colVector operator*(const double&, const colVector&);
friend colVector operator/(const colVector&, const colVector&);
friend colVector operator/(const colVector&, const double&);
friend colVector operator/(const double&, const colVector&);
// dot product, legality wil not be checked!!
friend double dotProduct(const colVector&, const colVector&);
// magnitude, i.e., 2nd norm
friend double norm(const colVector&);
// unit
friend colVector unit(const colVector&);
// outputstream operator <<
friend std::ostream& operator<<(std::ostream&, const colVector&);
// inputstream operator >>
friend std::istream& operator>>(std::istream&, colVector&);
};
// For MSV 2019, need to be declared outside again! Do not know why!!
// outputstream operator <<
std::ostream& operator<<(std::ostream&, const colVector&);
// inputstream operator >>
std::istream& operator>>(std::istream&, colVector&);
#endif
colVector.cpp 文件
// 2020-07-09
// class colVector - cpp file
#include "colVector.h"
#include <math.h>
// constructors
// construct with size and val
colVector::colVector(unsigned int nSize, double dVal):
m_nSize(nSize), m_pdColVct(nullptr)
{
//std::cout << "Construct by size and dValue. " << std::endl;
if (nSize > 0) // ask memory
m_pdColVct = new double[nSize];
for (unsigned i = 0; i < nSize; ++i) // assign value
m_pdColVct[i] = dVal;
}
// copy constructor, deep copy
colVector::colVector(const colVector& colVct)
{
//std::cout << "Copy constructor. " << std::endl;
m_nSize = colVct.m_nSize;
m_pdColVct = nullptr;
if (m_nSize > 0) // ask memory
m_pdColVct = new double[m_nSize];
for (unsigned i = 0; i < m_nSize; ++i) // assign value
m_pdColVct[i] = colVct.m_pdColVct[i];
}
// copy assignment, deep copy
colVector& colVector::operator=(const colVector& colVct)
{
//std::cout << "Copy assignment. " << std::endl;
if (this == &colVct)
return *this;
if (m_pdColVct != nullptr) // free old memory
delete[] m_pdColVct;
m_nSize = colVct.m_nSize;
if (m_nSize > 0) // ask new memory
m_pdColVct = new double[m_nSize];
for (unsigned i = 0; i < m_nSize; ++i) // copy value
m_pdColVct[i] = colVct.m_pdColVct[i];
return *this;
}
// move constructor, shallow copy while keep memory
colVector::colVector(colVector&& colVctRhs) noexcept:
m_nSize(colVctRhs.m_nSize), m_pdColVct(colVctRhs.m_pdColVct)
{
//std::cout << "move constructor" << std::endl;
colVctRhs.m_nSize = 0;
// set rhs value ptr to nullptr, thus in destructor
// its memory will be kept! Beautiful!
colVctRhs.m_pdColVct = nullptr;
}
// move assignment, shallow copy while keep memory
colVector& colVector::operator=(colVector&& colVctRhs) noexcept
{
//std::cout << "move assignment. " << std::endl;
if (this == &colVctRhs) // prevent self assignment
return *this;
// free old memory
m_nSize = 0;
if (m_pdColVct != nullptr)
delete[] m_pdColVct;
// move pointers
m_nSize = colVctRhs.m_nSize;
m_pdColVct = colVctRhs.m_pdColVct;
// let right hand side object null so destructor will keep memory
colVctRhs.m_nSize = 0;
colVctRhs.m_pdColVct = nullptr;
// return
return *this;
}
// destructor
colVector::~colVector()
{
//std::cout << "Destructor. " << *this << std::endl;
if (m_pdColVct != nullptr) // free memory
delete[] m_pdColVct;
m_pdColVct = nullptr;
m_nSize = 0;
}
// get value
double colVector::getCompIdx(unsigned int nIdx) const
{
if (nIdx < m_nSize)
return m_pdColVct[nIdx];
else
return 0.0; // no error message will output or exit
}
// set value
void colVector::setCompIdx(unsigned int nIdx, double val)
{
if (nIdx < m_nSize) // only correct position will be set value
m_pdColVct[nIdx] = val;
}
// set all
void colVector::setAll(double val)
{
for (unsigned i = 0; i < m_nSize; ++i)
m_pdColVct[i] = val;
}
// operator [] to fetch value
double& colVector::operator[](unsigned int nIdx)
{
return m_pdColVct[nIdx]; // do not check if nIdx is correct
}
const double& colVector::operator[](unsigned int nIdx) const
{
return m_pdColVct[nIdx]; // do not check if nIdx is correct
}
// operator += -= *= /=, legality wil not be checked!!
colVector& colVector::operator+=(const colVector& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] += colVct.m_pdColVct[i];
return *this;
}
colVector& colVector::operator+=(const double& dVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] += dVal;
return *this;
}
colVector& colVector::operator-=(const colVector& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] -= colVct.m_pdColVct[i];
return *this;
}
colVector& colVector::operator-=(const double& dVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] -= dVal;
return *this;
}
colVector& colVector::operator*=(const colVector& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] *= colVct.m_pdColVct[i];
return *this;
}
colVector& colVector::operator*=(const double& dVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] *= dVal;
return *this;
}
colVector& colVector::operator/=(const colVector& colVct)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] /= colVct.m_pdColVct[i];
return *this;
}
colVector& colVector::operator/=(const double& dVal)
{
for (unsigned int i = 0; i < m_nSize; ++i)
m_pdColVct[i] /= dVal;
return *this;
}
// friend + - * /, legality will not be checked!
colVector operator+(const colVector& lhs, const colVector& rhs)
{
colVector colVctTmp(lhs);
colVctTmp += rhs;
return colVctTmp;
}
colVector operator+(const colVector& lhs, const double& dVal)
{
colVector colVctTmp(lhs);
colVctTmp += dVal;
return colVctTmp;
}
colVector operator+(const double& dVal, const colVector& rhs)
{
colVector colVctTmp(rhs);
colVctTmp += dVal;
return colVctTmp;
}
colVector operator-(const colVector& lhs, const colVector& rhs)
{
colVector colVctTmp(lhs);
colVctTmp -= rhs;
return colVctTmp;
}
colVector operator-(const colVector& lhs, const double& dVal)
{
colVector colVctTmp(lhs);
colVctTmp -= dVal;
return colVctTmp;
}
colVector operator-(const double& dVal, const colVector& rhs)
{
colVector colVctTmp(rhs.m_nSize, dVal);
colVctTmp -= rhs;
return colVctTmp;
}
colVector operator*(const colVector& lhs, const colVector& rhs)
{
colVector colVctTmp(lhs);
colVctTmp *= rhs;
return colVctTmp;
}
colVector operator*(const colVector& lhs, const double& dVal)
{
colVector colVctTmp(lhs);
colVctTmp *= dVal;
return colVctTmp;
}
colVector operator*(const double& dVal, const colVector& rhs)
{
colVector colVctTmp(rhs.m_nSize, dVal);
colVctTmp *= rhs;
return colVctTmp;
}
colVector operator/(const colVector& lhs, const colVector& rhs)
{
colVector colVctTmp(lhs);
colVctTmp /= rhs;
return colVctTmp;
}
colVector operator/(const colVector& lhs, const double& dVal)
{
colVector colVctTmp(lhs);
colVctTmp /= dVal;
return colVctTmp;
}
colVector operator/(const double& dVal, const colVector& rhs)
{
colVector colVctTmp(rhs.m_nSize, dVal);
colVctTmp /= rhs;
return colVctTmp;
}
// dot product
double dotProduct(const colVector& lhs, const colVector& rhs)
{
double dVal = 0.0;
for (unsigned int i = 0; i < lhs.m_nSize; ++i)
dVal += (lhs.m_pdColVct[i] * rhs.m_pdColVct[i]);
return dVal;
}
// magnitude, i.e., 2nd norm
double norm(const colVector& colVct)
{
return sqrt(dotProduct(colVct, colVct));
}
// unit
colVector unit(const colVector& colVct)
{
return (colVct / norm(colVct));
}
// operator <<
std::ostream& operator<<(std::ostream& os, const colVector& colVct)
{
if (colVct.m_nSize == 0)
os << "Empty Column Vector! ";
else
{
os << "[";
for (unsigned int i = 0; i < colVct.m_nSize - 1; ++i)
os << colVct[i] << "; ";
os << colVct[colVct.m_nSize - 1] << "]";
}
return os;
}
// operator >>
std::istream& operator>>(std::istream& is, colVector& colVct)
{
if (colVct.m_nSize != 0)
{
colVct.m_nSize = 0;
delete [] colVct.m_pdColVct; // free memory
colVct.m_pdColVct = nullptr;
}
is >> colVct.m_nSize;
if (!is)
{
colVct.m_nSize = 0;
return is;
}
colVct.m_pdColVct = new double[colVct.m_nSize];
for (unsigned int i = 0; i < colVct.m_nSize; ++i)
{
is >> colVct.m_pdColVct[i];
if (!is)
colVct.m_pdColVct[i] = 0.0;
}
return is;
}
测试主函数main.cpp
// 2020-07-09
// main function - test class colVector
// Author: Guanhua Mei
#include <iostream>
#include "colVector.h"
using namespace std;
int main()
{
colVector colVct1;
cout << colVct1 << endl;
colVector colVct2(2, 3.14);
cout << colVct2 << endl;
cout << "Please input a column vector in format "
<< "nSize a0 a1 a2 ... aN: " << endl;
cin >> colVct1;
cout << colVct1 << endl;
colVector colVct3(2, 9);
colVct3.setCompIdx(0, 3);
colVct3.setCompIdx(1, 4);
colVct2.setCompIdx(0, 1);
colVct2.setCompIdx(1, 2);
cout << "colVct2: " << colVct2 << endl;
cout << "colVct3: " << colVct3 << endl;
colVector colVct4(colVct3);
cout << colVct4 << endl;
colVct4.setAll(9);
cout << colVct4 << endl;
cout << colVct3.getCompIdx(0) << endl;
cout << colVct3[1] << endl;
cout << (colVct3 += 1.0) << endl;
cout << (colVct3 -= 1.0) << endl;
cout << (colVct3 *= 2.0) << endl;
cout << (colVct3 /= 2.0) << endl << endl;
cout << (colVct3 += colVct2) << endl;
cout << (colVct3 -= colVct2) << endl;
cout << (colVct3 *= colVct2) << endl;
cout << (colVct3 /= colVct2) << endl << endl;
cout << (colVct3 + colVct2) << endl;
cout << (colVct3 - colVct2) << endl;
cout << (colVct3 * colVct2) << endl;
cout << (colVct3 / colVct2) << endl << endl;
cout << (colVct3 + 1.0) << endl;
cout << (colVct3 - 1.0) << endl;
cout << (colVct3 * 2.0) << endl;
cout << (colVct3 / 2.0) << endl << endl;
cout << (1.0 + colVct3) << endl;
cout << (1.0 - colVct3) << endl;
cout << (2.0 * colVct3) << endl;
cout << (2.0 / colVct3) << endl << endl;
cout << dotProduct(colVct2, colVct3) << endl;
cout << norm(colVct3) << endl;
cout << unit(colVct3) << endl;
return 0;
}
测试结果,表明所有函数均实现了其功能。