c++入门之 再话类
对于类,其结构并不难,但要理解其设计思想也并不容易,在此,我们可以通过下面的代码进一步理解和使用类:
# ifndef VECTOR_H_
# define VECTOR_H_
# include "iostream" namespace VECTOR //注意,这里对这个类定义了名称空间,实际上,在写自己的类时,也应该定义自己的名称空间
{
class Vector
{
public:
enum Mode{RECT,POL};//因为这个量需要用户自己去设定
private: //注意:私有成员(无论是函数还是变量)只能被类内部成员访问
double x;
double y;
double mag;
double ang;
Mode mode; 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();
void rect_mode(); Vector operator+(const Vector &b) const;
Vector operator-(const Vector &b) const;
Vector operator-() const;
Vector operator*(double n) const; friend Vector operator*(double n, const Vector &a);//注意这里采用了友元函数的做法,应该显示包含所有参数
friend std::ostream & operator<<(std::ostream &os, const Vector & v);//昨天没有思考返回引用是否存在问题???因为局部变量被销毁的问题
}; }
# endif
该类定义中:除了备注的一些以外,总结这么几点:
1 定义了一个类的时候,限定了该类的名称空间通常是一件好事,以免自己的变量和别人的发生了冲突
2 公有还是私有并无界限之分,完全取决于程序的功能。
3 我们通常会发现:当定义一个类成员函数时,通常需要:构造函数,析构函数,甚至友元函数
4 私有成员(无论是变量还是函数)只能被类内部的成员进行访问,而共有成员 可以被其他类甚至其他任何东西访问。究其本质:公有部分 是提供的接口
下面给出该定义:
# include"cmath" //从下文的调用方法来看,这里应该是函数库,而不是类库
# include "vector.h"
using std::sqrt; //注意 std 包含了很多
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_ang()
{
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);
} 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;
set_x();
set_y();
}
else
{
cout << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0\n";
x = y = mag = ang = 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 << "Incorrect 3rd argument to Vector()--";
cout << "vector set to 0\n";
x = y = mag = ang = 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(n*x,x*y)
}
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";
}
}
1. 我们注意107行和112行的代码:本质上,进行了加法和减法之后,得到的是一个新的类对象,但由于这个类对象不止一种表示形式(直角坐标和极坐标),这里巧妙的利用了 返回构造函数的执行。这告诉我们:构造函数并不仅仅用于初始化,构造函数的本意:构造新的对象,一定要认识这一本质特征和思想。
2 我们注意124行的代码:return a*n; 本质上,对象乘以一个数无法实现,但这里,其实,并没有返回,而是回去重新调用了上面的*。
3 注意:129行和131行:if (v.mode == Vector::RECT)。为何要加Vector::RECT而不是RECT,这是因为:
友元函数虽然在public中,但友元函数并不在类作用域中!!! 这对于所有友元函数都成立!!!
c++入门之 再话类的更多相关文章
- c++入门之再话内存和引用
此处没有代码,仅仅讨论一些这样的问题:我们为何使用引用?在哪里使用引用? 首先从函数的角度思考?:函数进行一般参数传递的时候,是怎么样传递的?普通类型的参数传递,是将传递的实参复制一份,到另一个内存空 ...
- c++入门之再话命名空间的意义
c++中使用了命名空间这一概念,通过下面这个代码,我们将深刻认识到命名空间的重要作用和意义: # include"iostream" using namespace std; na ...
- JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...
- Python编程从入门到实践笔记——类
Python编程从入门到实践笔记——类 #coding=gbk #Python编程从入门到实践笔记——类 #9.1创建和使用类 #1.创建Dog类 class Dog():#类名首字母大写 " ...
- python入门学习:8.类
python入门学习:8.类 关键点:类 8.1 创建和使用类8.2 使用类和实例8.3 继承8.4 导入类 8.1 创建和使用类 面向对象编程是最有效的软件编写方法之一.在面向对象编程中,你编写 ...
- Node.js开发入门—HelloWorld再分析
在Node.js开发入门(1)我们用http模块实现了一个简单的HelloWorld站点,这次我们再来细致分析下代码.了解很多其它的细节. 先看看http版本号的HelloWorld代码: 代码就是这 ...
- Python 3 快速入门 3 —— 模块与类
本文假设你已经有一门面向对象编程语言基础,如Java等,且希望快速了解并使用Python语言.本文对重点语法和数据结构以及用法进行详细说明,同时对一些难以理解的点进行了图解,以便大家快速入门.一些较偏 ...
- 【PHP面向对象(OOP)编程入门教程】11.类的继承
继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用,好像没听说哪个面向对象的语言不支持继承. 继承是PHP5面象对象程序设计的重要特性之一,它是指建立一个新的派生类,从一个或 ...
- Java+7入门经典 - 6 扩展类与继承 Part 1/2
第6章 扩展类与继承 面向对象编程的一个重要特性: 允许基于已定义的类创建新的类; 6.1 使用已有的类 派生 derivation, 派生类 derived class, 直接子类 direct s ...
随机推荐
- [HBase_3] HBase 命令
0. 说明 1. HBase 命令 1.1 HBase 与 SQL 的区别 1.2 合并 HBase 中的小文件 major_compact 'test:t1' 1.3 删除数据的区别 HBase 在 ...
- 解决git push时发现有超过100M的文件时,删除文件后,发现还是提交不上去的问题
我这里故意放了一个超过100M的文件 后续,git add ,git commit 然后,git push 此时会发现出现了错误.如果,我们再这里直接在文件系统中删除这个大的文件,然后再次提交,会发现 ...
- June. 21 2018, Week 25th. Thursday
Summertime is always the best of what might be. 万物最美的一面,总在夏季展现. From Charles Bowden. It was June, an ...
- Linux之文档与目录结构
Linux文件系统结构 Linux目录结构的组织形式和Windows有很大的不同.首先Linux没有“盘(C盘.D盘.E盘)”的概念.已经建立文件系统的硬盘分区被挂载到某一个目录下,用户通过操作目录来 ...
- 1. 路过面了个试就拿到2个offer。是运气吗?
路过随便面个试就拿到2个offer.是运气吗? #复习很重要#看看面试问的问题,再瞧瞧师兄的学习态度,你就明白 机会为何总与你擦肩而过了.[玫瑰] 以下是我和师兄的聊天记录,你会几个?
- (转)Spring Boot 2 (七):Spring Boot 如何解决项目启动时初始化资源
http://www.ityouknow.com/springboot/2018/05/03/spring-boot-commandLineRunner.html 在我们实际工作中,总会遇到这样需求, ...
- C#深度学习のTask(基于任务的异步模型)
一.Task关键字解释 Task 类的表示的单个操作不会返回一个值,通常以异步方式执行. Task 对象是一种的中心思想 基于任务的异步编程模式 首次引入.NET Framework 4 中. 因为由 ...
- Interrupt
Interrupt ,给线程发送一个中断信号 给t1线程发送了中断信号,t1对线程的中断信号判断后,跳出循环,线程t1运行结束 public class Demo { public static vo ...
- 转://工作中 Oracle 常用数据字典集锦
DBA工作中数据字典就等同于我们本和笔,时时刻刻也分不开的,不管是看状态,还是监控,都需要数据字典的支持,本文整理出来常用的数据字典系列,帮助大家来记住和汇总以便查询利用 ALL_CATALOG Al ...
- 【转】用ffmpeg转多音轨的mkv文件
命令: ffmpeg -i AmericanCaptain.mkv -map 0:v -vcodec copy -map 0:a:1 -acodec copyAmericanCaptain.mp4 - ...