IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 第四周 第三部分 -> 正文阅读

[C++知识库]C++ 第四周 第三部分

使用类

运算符重载

? ? ? ?运算符是一种形式的C++多态。实际上,很多C++运算符已经被重载,比如 * ,可以将它用于地址,也可以表示两个数字相乘。C++ 将运算符重载扩展到用户定义的类型

? ? ? ?要重载运算符,需要使用被称为运算符函数的特殊函数形式,格式如下:

operatorop(argument-list)

? ? ? ?例如:,operator +() 重载的是 + 运算符。op 必须是有效运算符,不能虚构出新的符号。燃鹅, operator [ ]()函数将重载 [ ] 运算符,因为 [ ] 是数组索引运算符。

? ? ? ?下面是一个示例:

// mytime.h
#ifndef MYTIME_H_
#define MYTIME_H_

class Time
{
	private:
		int hours;
		int minutes;
	public:
		Time();
		Time(int h,int m = 0);
		void AddMin(int m);
		void AddHr(int h);
		void Reset(int h = 0,int m = 0);
		Time operator+(const Time & t) const;    // 运算符重载
		void Show() const;
};
#endif
// mytime.cpp
#include<iostream>
#include "mytime.h"

Time::Time()
{
	hours = minutes = 0;
}

Time::Time(int h, int m)
{
	hours = h;
	minutes = m;
}

void Time::AddMin(int m)
{
	minutes += m;
	hours += minutes / 60;
	minutes %= 60;
}

void Time::AddHr(int h)
{
	hours += h;
}

void Time::Reset(int h, int m)
{
	hours += h;
	minutes = m;
}

Time Time::operator+(const Time & t) const
{
	Time sum;
	sum.minutes = minutes+ t.mintues;
	sum.hours = hours + t.hours + sum.minutes / 60;
	sum.minutes %= 60;
	return sum;
}

void Time::Show() const
{
	std::cout << hours << " hours, " << minutes << " minutes";
}

重载限制

? ? ? ?1. 重载后的运算符必须至少有一个操作数是用户定义的类型这将防止用户为标准类型重载运算符。因此,不能将减法运算符重载为计算两个double 值的和。这将保证程序正常运行。

? ? ? ?2. 使用运算符不能违法运算符原来的句法规则。例如,不能将求模运算符(%)重载成使用一个操作数:

int x;
Time shvia;
& x;        // invalid
% shvia     // invalid

? ? ? ? 同样,不能修改运算符的优先级。

? ? ? ? 3.? 不能创建新的运算符。例如,不能定义 operator ** () 函数来表示求幂。

? ? ? ? 4. 不能重载下面的运算符:

sizeof
.                
.*                //  成员指针运算符 
::
?:
typeid            // 一个 RTTI 运算符 

// 下面四个都是强制类型转换运算符 
// 用法: 强制类型转换运算符 <typename> (expression) 

const_cast        // const_cast<>里边的内容必须是引用或者指针

reinterpret_cast  // 1 改变指针或引用的类型
                  // 2 将指针或引用转换为一个足够长度的整形
                  // 3 将整型转换为指针或引用类型
                  
dynamic_cast      // 1 其他三种都是编译时完成的,dynamic_cast 是运行时处理的,运行时要进行类型检查
                  // 2 不能用于内置的基本数据类型的强制转换
                  // 3 dynamic_cast 要求 <> 内所描述的目标类型必须为指针或引用
                  // 4 使用 dynamic_cast 进行转换的,基类中一定要有虚函数,否则编译不通过
                  
static_cast       // 基本数据类型之间的转换 

? ? ? ? ?下面的运算符只能通过成员函数就行重载:

=
()
[]
->

?

友元

? ? ? ?C++ 控制对类对象私有部分的访问。通常,公有类方法提供了唯一的访问途径,但有时候这种限制不合理。C++ 提供另一种形式的访问权限:友元。

? ? ? ?友元有三种:

1. 友元函数;

2. 友元类

3. 友元成员函数.

创建友元

? ? ? 创建友元函数的第一步是将其原型放在类声明中,并再原型声明前加上关键字 friend:

friend Time operator* (double m, const Time & t);

? ? ? 该原型意味着下面两点:

1. 虽然 operator* () 函数是在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用;

2. 虽然 operator* () 函数不是成员函数,但它的访问权限与之成员函数相同.

?

? ? ? 第二步,函数定义不要使用关键字 friend,不要使用 Time : : 限定符:

Time operator* (double m, const & t)
{
	Time result;
	long totalminutes = t.hours * m * 60 + t.minutes * m;
	result.hours = totalminutes / 60;
	result.minutes = totalminutes % 60;
	return result;
}

? ? ? ? 实际上,按下面的方式对定义进行修改(交换乘法操作数的顺序),可以将这个友元函数编写为非友元函数:

Time operator* (double m, const & t)
{
	return t * m;
}

? ? ? ? ?提示:如果要为类 重载 运算符,并将非类的项作为其第一个操作数,则可以用友元函数来反转操作数的顺序.

重载 << 运算符

??

<< 的第一种版本

? ? ? ?要使?Time 类知道使用 cout , 必须使用友元函数。这是什么原因呢?因为下面这样的语句使用俩个对象,其中第一个是 ostream 类对象(cout):

cout << trip;

? ? ? ?如果使用一个 Time 成员函数来重载 << ,Time 对象将是一个操作数,就像使用成员函数重载

?* 运算符那样。这意味着必须这样使用 << :

trip << cout;  // if operator<<() were a Time member function

? ? ? ?这样会令人疑惑。但通过友元函数,可以像下面这样重载运算符:

void operator<<(ostream & os, const Time & t)
{
	os << t.hours << " hours, " << t.minutes << " minutes";
}

? ? ? ? 这样可以使用下面的语句:

cout << trip;

?

<< 的第二种重载版本

?

重载运算符:作为成员函数还是非成员函数

?

?

一个矢量类

? ? ? ?直接上代码

// vect.h
#ifndef VECTOR_H_
#define VECTOR_H_
#include<iostream>
name space VECTOR
{
	class vector
	{
		public:
			enum Mode (RECT, POL);
		private:
			double x;         // horizontal value 
			double y;         // vertical value
			double mag;       // lenth of vector
			double ang        // direction of vector in degrees
			Mode mode;        // RECT of POL
			void set_mag();
			void set_ang();
			void set_x();
			void set_y();
		public:
			Vector();
			 Vector(double n1, double n2, Mode form = RECT);
			 void reset(double n1, double n2, Mode form = RECT);
			 ~Vector();
			 double xval() const (return x;)
			 double yval() const (return y;)
			 double magval() const (return mag;)
			 double angval() const (return ang;)
			 void polar_mode();               // set mode to POL
			 void rect_mode();                // set mode to RECT
	    // operator overloading
	        Vector operator+(const Vector & a) const;
	        Vector operator-(const Vector & b) const;
	        Vector operator-() const;
	        Vector operator*(double n) const;
	    // friends
	        friend Vector operator*(double n, cosnt Vector & a);
	        friend std::ostream &
	               operator<<(std::ostream & os, const Vector & v);
	};
}
#endif
// vect.cpp
#include<cmath>
#include "vect.h"
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR
{
	const double Rad_to_deg = 45.0 / atan(1.0);

	void Vector::set_mag()
	{
		mag = sqrt(x * x * y * y);
	}

	void Vector::set_ang()
	{
		if(x == 0.0 && y == 0.0)
		{
			ang = 0.0;
		}
		else
		{
			ang = atan2(y, x);
		}
	}

	void Vector::set_x()
	{
		x = mag * cos(ang);
	}

	void Vector::set_y()
	{
		y = mag * sin(ang);
	}
    
    // public method
	Vector::Vector()
	{
        x = y = mag = ang = 0.0;
        mode = RECT;
	}
	
	Vector::Vector(double n1, double n2, Mode form)
	{
		mode = form;
		if(form == RECT)
		{
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		}
		else if(form == POL)
		{
			mag = n1;
			ang = n2;    // Rad_to_deg
			set_x();
			set_y();
		}
		else
		{
			cout << "Incorrent 3rd argument to Vector() == ";
			cout << "vetcor set to 0\n";
			x = y = mag = deg = 0.0;
			mode = RECT;
		} 
	}
	
	void Vector:: reset(double n1, double n2, Mode form)
	{
		mode = form;
		if(form == RECT)
		{
			x = n1;
			y = n2;
			set_mag();
			set_ang();
		}
		else if(form == POL)
		{
			mag = n1;
			ang = n2;
			set_x();
			set_y();
		}
		else
		{
			cout << "Incorrent 3rd argument to Vector() == ";
			cout << "vetcor set to 0\n";
			x = y = mag = deg = 0.0;
			mode = RECT;
		}
	}
	
	Vector:~Vector()
	{
	}
	
	void Vector::polar_mode()
	{
		mode = POL;
	}
	
	void Vector::rect_mode()
	{
		mode = RECT;
	}
	
	Vector Vector::operator+(const Vector & b) const
	{
		return Vector(x + b.x, y + b.y);
	}
	
	Vector Vector::operator-(const Vector & b) const
	{
		return Vector(x - b.x, y - b.y);
	}
	
    Vector Vector::operator-() const
    {
    	return Vector(-x, -y);
	}
	
	Vector Vector::operator*(double n) const
	{
		return Vector(n * x, n * y);
	}
	
	// friend methods
	Vector operator*(double n, const Vector & a)
	{
		return a * n;
	}
	
	std::ostream & operator<<(std::ostream & os, const Vector & v)
	{
		if(v.mode == Vector::RECT)
		{
			os << "(x,y) = (" << v.x << ", " << v.y << ")";  
		}
		else if(v.mode == Vector::POL)
		{
			os << "(m,a) = (" << v.mag << ", 
			    << v.ang * Rad_to_deg << ")";
		}
		else
		{
			os << "Vector object mode is invalid";
		}
		return os;
	}
}

?

?

?

?

转换函数

? ? ? ?格式:

operator typeName();
// 转换函数必须是类方法
// 不能指定返回类型
// 不能有参数

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-26 21:57:27  更:2021-12-26 21:57:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:43:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码