C++ Primer笔记10_运算符重载_赋值运算符_进入/输出操作符
1.颂值运营商
首先来福值运算符引入后面要说的运算符重载。上一节说了构造函数、拷贝构造函数;一个类要想进行更好的控制。须要定义自己的构造函数、拷贝构造函数、析构函数、当然,还有赋值运算符。常说的三大函数就是指拷贝、赋值、析构。
假设一个类不定义自己的赋值运算符。会自己生成一个默认的赋值运算操作。这个默认的赋值运算满足一般类的需求。它实现的是一个浅拷贝。可是当类的功能、作用逐渐完好时,就会出现非常多问题。所以,通过自己定义赋值运算符来控制赋值操作时类的行为是非常有必要的。当一个类的对象与对象之间发生赋值(=)运算时,就会调用重载的赋值运算符函数。
还是以上节的样例来说。看代码:
#include <iostream>
#include <new>
#include <string> using namespace std; class Person
{
public:
Person();
Person(int n, const string &str);
Person(const Person &n);
Person &operator=(const Person &p);//赋值运算符函数
~Person();
private:
int age;
string *name;
}; Person::Person():age(0), name(NULL)
{
cout << "Default Person" << endl;
} Person::Person(int n, const string &str):age(n), name(new string(str))
{
cout << "Init Person" << endl;
} Person::Person(const Person &n)
{
if(n.name)
{
name = new string(*(n.name));
age = n.age;
}
else
{
name = NULL;
age = 0;
}
} Person & Person::operator=(const Person &p)
{
if(this == &p)
{
return *this;//推断传入的对象是否是当前对象本身
}
string *tmp = new string(*p.name);//又一次分配一段空间
delete this->name;//释放原空间
this->name = tmp;
this->age = p.age; return *this;
} Person::~Person()
{
cout << "~Person " << "name: " << name << " age: " << age << endl;
delete name;
} int main()
{
Person p1(20, "SCOTT");
Person p2;
p2 = p1; return 0;
}
在这里,假设没有自己定义赋值运算符,当执行P2 = P1时,是没有错的。而错误会处在析构部分,上一篇文章中已经说明原因。
Init Person
Default Person
~Person name: 0x8264020 age: 20
~Person name: 0x8264020 age: 20
Segmentation fault (core dumped)——段错误!
自己定义赋值运算符之后。执行结果例如以下:
Init Person
Default Person
~Person name: 0x8121030 age: 20
~Person name: 0x8121020 age: 20
注意:
1)一般来说,大多数赋值运算符函数组合了析构函数和拷贝构造函数的工作。
2)假设讲一个对象赋予它自身。赋值运算符必须能正确的工作。
3)当编写赋值运算符函数时。一个好的模式是将右側对象复制到一个局部暂时对象中。拷贝完毕后,销毁左側对象的现有成员就是安全的了。
然后将数据从暂时对象复制到左側对象。
2.运算符重载
上面是众多运算符重载的一个实例。重载的运算符是具有特殊名字的函数:它们的名字是由keywordoperator和其后要定义的运算符号共同组成。
它与普通函数一样也有返回值、參数列表、以及函数体。
重载运算符函数的參数数量与该运算符的作用的运算对象数量一样多。一元运算符有一个參数。二元运算符有两个。
对于二元运算符来说,左側运算对象传递给第一个參数,右側运算对象传递给第二个參数。
假设一个运算符函数是成员函数,则它的第一个(左側)运算对象绑定到隐式的this指针上。因此,成员运算符函数的參数比运算符的运算对象少一个。(如上例中的=运算符)
2.1 输入、输出运算符
IO标准库分别使用>>和<<运行输入和输出操作。
类能够按须要来自己定义输入、输出运算符。
样例:
#include <iostream>
#include <new>
#include <string> using namespace std; class Person
{
public:
Person();
Person(int n, const string &str);
Person(const Person &n);
Person &operator=(const Person &p);
~Person(); string getName()const;
friend ostream &operator<<(ostream &out, const Person &p);//输出运算符
friend istream &operator>>(istream &in, Person &p);//输入运算符
private:
int age;
string *name;
}; Person::Person():age(0), name(NULL)
{
cout << "Default Person" << endl;
} Person::Person(int n, const string &str):age(n), name(new string(str))
{
cout << "Init Person" << endl;
} Person::Person(const Person &n)
{
if(n.name)
{
name = new string(*(n.name));
age = n.age;
}
else
{
name = NULL;
age = 0;
}
} Person & Person::operator=(const Person &p)
{
if(this == &p)
{
return *this;
}
string *tmp = new string(*p.name);
delete this->name;
this->name = tmp;
this->age = p.age; cout << "operator =" << endl; return *this;
} Person::~Person()
{
cout << "~Person " << "name: " << name << " age: " << age << endl;
delete name;
} string Person::getName()const
{
if(name)
{
return *name;
}
return string();
}
//重载输出运算符
ostream &operator<<(ostream &out, const Person &p)
{
out << "p.age: " << p.age << ", p.name: " << p.getName();
return out;
}
//重载输入运算符
istream &operator>>(istream &in, Person &p)
{
string s;
cout << "please input age and name:";
in >> p.age >> s;
if(in)//推断是否读取正确
{
p.name = new string(s);
}
else
{
p = Person();
} return in;
} int main()
{
Person p1(20, "SCOTT");
Person p2(10, "Kate");
Person p3;
/*
cout << p1 << endl;
cout << p2 << endl;
cout << p3 << endl;
*/
cin >> p3;
cout << p3 << endl; return 0;
}
执行程序,输入12 Mike, 结果例如以下:
Init Person
Init Person
Default Person
please input age and name:12 Mike
p.age: 12, p.name: Mike
~Person name: 0x939a088 age: 12
~Person name: 0x939a048 age: 10
~Person name: 0x939a020 age: 20
总结:
1.输入、输出运算符必须是非成员函数。
2.输入、输出运算符一般声明为友元类型。
3.输出运算符函数中第二个參数能够声明为const型,由于不须要改变其值。而输入运算符的第二个參数不能为const,由于它要接受输入。另外,返回值最好是引用,避免了值拷贝过程。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
C++ Primer笔记10_运算符重载_赋值运算符_进入/输出操作符的更多相关文章
- C++ Primer笔记13_运算符重载_总结
总结: 1.不能重载的运算符: . 和 .* 和 ?: 和 :: 和 sizeof 和 typeid 2.重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则例如以下: 运算符 建议使用 ...
- C++ Primer笔记12_运算符重载_递增递减运算符_成员訪问运算符
1.递增递减运算符 C++语言并不要求递增递减运算符必须是类的成员.可是由于他们改变的正好是所操作对象的状态.所以建议设定为成员函数. 对于递增与递减运算符来说,有前置与后置两个版本号,因此.我们应该 ...
- C++学习笔记之运算符重载
一.运算符重载基本知识 在前面的一篇博文 C++学习笔记之模板(1)——从函数重载到函数模板 中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标 ...
- 《Inside C#》笔记(十一) 运算符重载
运算符重载与之前的索引器类似,目的是为了让语言本身使用起来更方便直接,也是一种语法糖. 一 运算符重载(Operator Overloading) 运算符重载的存在,使得现有的各种运算符可以被重新定义 ...
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
运算符重载 重载的运算符是具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成.重载的运算符是遵循函数重载的选择原则,根据不同类型或不同参数来选择不同的重载运算符. 运 ...
- lintcode-208-赋值运算符重载
208-赋值运算符重载 实现赋值运算符重载函数,确保: 新的数据可准确地被复制 旧的数据可准确地删除/释放 可进行 A = B = C 赋值 说明 本题只适用于C++,因为 Java 和 Python ...
- C++学习(12)—— 运算符重载
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型 1.加号运算符重载 作用:实现两个自定义数据类型相加的运算 #include <iostream> #i ...
- 新标准C++程序设计读书笔记_运算符重载
形式 返回值类型 operator 运算符(形参表) { …… } 运算符重载 (1)运算符重载的实质是函数重载(2)可以重载为普通函数,也可以重载为成员函数 class Complex { publ ...
- c++中的运算符重载operator2(翁恺c++公开课[31-33]学习笔记)
上一篇operator1中,大概说了下重载的基本用法,接下来对c++中常见的可重载运算符归一下类,说一下它们的返回值,讨论下较为复杂的运算符重载上的坑
随机推荐
- IDL 自己定义功能
function add,x,y return, x+y end pro sum x=1 y=2 print,add(x,y) end 版权声明:本文博客原创文章,博客,未经同意,不得转载.
- SQL ---指令实例语句
1 1 create database+数据库名字 创建数据库 2 2 create table+表的名字 创建表 3 表中的操作: 4 3 insert into 表名 (列名1,列名2··)val ...
- Activity组件的生命周期
一.Activiy组件的三个状态: 1.前台状态(active) : 在屏幕的最上层,页面获得焦点,可以响应用户的操作2.可视状态(paused) : 不能与用户交互,但是还存在于可视区域内,它依然存 ...
- linux下 文件IO 相关
linux下操作文件或设备,需要一个文件描述符 file descriptor,fd 来引用.fd是一个非负整数,实际上是一个索引值,指向文件的记录表,对文件的操作都需要fd.默认的几个:标准输入流 ...
- Twenty Newsgroups Classification实例任务之TrainNaiveBayesJob(一)
接着上篇blog,继续看log里面的信息如下: + echo 'Training Naive Bayes model' Training Naive Bayes model + ./bin/mahou ...
- 字符串转换为整数”123“->123
字符串转换为整数"123"->123 题目描写叙述: 输入一个由数字组成的字符串.把它转换成整数并输出. 比如:输入字符串"123".输出整数123. 给 ...
- ThinkPHP 3.2 开发过程
原文:ThinkPHP 3.2 开发过程 设置所有项目的公共配置Application\Common\Conf\config.php,SAE模式下配置文件为config_sae.php 配置默认的模块 ...
- servlet其工作原理和例子证明
servlet简单介绍 当我们在地址栏里面输入www.baidu.com,终于呈如今我们面前的是百度搜索的页面.在这些訪问过程中,都会有一个webserver来处理这些请求以及訪问处理后的结果. 而s ...
- 使用VS插件在VS2012/2013上编辑和调试Quick-Cocos2d-x的Lua代码
vs 也能够做lua 开发,并进行代码调试 依照以下文档,调试没问题. 參考文档: 点击打开链接
- Java中的工具类和新特性
1:Collections集合框架工具类: /* 集合框架的工具类. Collections:集合框架的工具类.里面定义的都是静态方法. Collections和Collection有什么差别? Co ...