C++小例子——03 列向量类colVector

再来一个列向量类colVector。
其成员变量有两个,元素数目,和用于动态申请释放内存空间的double型指针。
其构造函数可由元素数目和元素值(列向量中所有元素都是同一个值)来构造,也可用另外一个列向量来构造(拷贝构造,copy constructor),析构函数用来释放存储空间,此外,还有拷贝赋值(copy assignment)函数,即用操作符等号=来实现深拷贝赋值操作,以及移动构造(move constructor)函数,用右值来做浅复制(仅复制指针地址),和移动赋值(move constructor)函数,重载操作符等号=,用右值来做浅复制。
其他成员函数包括提取第idx个分量的值,设置第idx个分量的值,设置整体元素的值,用操作符中括号[]来获取第idx个分量的引用(可以给第idx个元素做修改)和常引用(只能把第idx个元素拿出来用,不能修改),以及复合运算符+=、-=、*=、/=,用于和另一个colVector或double型变量的自身加减乘除操作,友元运算符+、-、*、/用于列向量colVector和另一个列向量或标量double型之间的加减乘除运算。提供了计算两个列向量点积的操作函数,计算列向量二范数的函数,以及单位化列向量的函数,当然都是友元函数。最后,还重载了输入流操作符>>和输出流操作符<<用来读入和输出列向量。

当然,还可以在外面定义矩阵和列向量的相乘函数,以及线性求解器用于求解Ax=B。

列向量类colVector的框架如下:

成员变量

  1. 列向量的元素数目
  2. double指针用于动态申请释放内存空间,来存储列向量元素

成员函数

  1. 构造函数1,元素数目,元素值,缺省值为0
  2. 拷贝构造,由另一个列向量构造
  3. 拷贝赋值,重载赋值运算符=,左列向量 = 右列向量,将右列向量的值赋给左列向量
  4. 移动构造,由右值列向量构造
  5. 移动赋值,重载赋值运算符=,左列向量 = 右值列向量,将右值列向量的值浅复制给左列向量
  6. 析构函数,释放内存空间
  7. 提取第idx个元素的值getCompIdx
  8. 设置第idx个元素的值setCompIdx
  9. 设置所有元素的值setAll
  10. 返回第idx个元素的引用,重载operator[]实现
  11. 返回第idx个元素的常引用,重载operator[]实现
  12. 操作符+=:列向量+=列向量/double
  13. 操作符-=:列向量-=列向量/double
  14. 操作符*=:列向量*=列向量/double
  15. 操作符/=:列向量/=列向量/double
  16. 友元操作符+:列向量+列向量,列向量+double,double+列向量
  17. 友元操作符-:列向量-列向量,列向量-double,double-列向量
  18. 友元操作符*:列向量*列向量,列向量*double,double*列向量
  19. 友元操作符/:列向量/列向量,列向量/double,double/列向量
  20. 友元函数dotProduct,计算两个列向量的点积
  21. 友元函数norm,计算列向量的二范数(也称模或幅值)
  22. 友元函数unit,计算列向量的单位化列向量
  23. 友元输入符>>,读入列向量
  24. 友元输出符<<,输出列向量

写好的程序如下:

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

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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在面向对象的编程,C语言并不直接支持和抽象的概念。引用提到,final关键字用来修饰方法,表示该方法不能在子被覆盖。而abstract关键字用来修饰抽象方法,表示该方法必须在子被实现。然而,在C语言,没有对应的关键字来实现和抽象的概念。 相反,C语言通过结构体来模拟的概念。结构体是一种用户自定义的数据型,可以包含多个不同型的数据成员。通过结构体,我们可以将相关的数据和功能组合在一起。然而,C语言的结构体不支持继承和多态等面向对象的特性。 在C语言,我们可以使用函数指针来模拟抽象和接口的概念。函数指针可以指向不同的函数,通过使用函数指针,我们可以实现多态性,即在运行时根据函数指针指向的具体函数来执行不同的操作。 综上所述,C语言并不直接支持面向对象和抽象的概念,但可以使用结构体和函数指针来实现似的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [面向对象——和对象](https://blog.csdn.net/shouyeren_st/article/details/126210622)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [面向对象编程原则(06)——依赖倒转原则](https://blog.csdn.net/lfdfhl/article/details/126673771)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值