【c++ primer, 5e】构造函数 & 拷贝、赋值和析构
【构造函数】
1、构造器就是创建对象时被调用的代码。
2、如果没有自定义构造器,那么编译器将自动合成一个默认的无参构造器。
3、自定义的构造器不允许加const,所创建const的对象只有在构造器代码执行完后,才被赋予const性质。
4、如果自定义了构造器,那么默认的构造器将无效化,可以理解为自定义内容覆盖了默认的内容。—— “要么什么都不做,要么全部都交给你来做。”
5、构造函数使用类内初始值并不是一个坏选择。
6、default。(在练习中体现)
7、构造函数初始值列表。(在练习中体现)
练习
7.11
ps:定义在类内的函数默认为内联的!类外的不是。(内联函数可以提高性能,那么,为什么不把所有函数都定义成内联函数呢?内联函数的优缺点)
#include <iostream>
#include <string>
using namespace std; // Sales_data.h
struct Sales_data {
// 新增的构造函数
Sales_data() = default; // 完全等同于合成默认构造器,不写就没有!!!
Sales_data(const string &s): bookNo(s) {} // “:”到“}”之间为构造函数初始值列表
Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
Sales_data(istream&);
// public部分,对象看起来是怎么样的。
std::string isbn() const { return bookNo; } // inline function
Sales_data& combine(const Sales_data&);
double avg_price() const;
// private部分,数据成员。
std::string bookNo;
unsigned units_sold = ;
double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&); // Sales_data.cpp
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
istream &read(istream &is, Sales_data &item)
{
double price = ;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
double Sales_data::avg_price() const {
if (units_sold)
return revenue/units_sold;
else
return ;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(istream &is)
{
read(is, *this);
} // main.cpp
int main()
{
Sales_data data1; // default
Sales_data data2("ISOD233");
Sales_data data3("ISOD233", , 22.5);
Sales_data data4(cin); print(cout, data1) << endl;
print(cout, data2) << endl;
print(cout, data3) << endl;
print(cout, data4) << endl;
/* output:
0 0 0
ISOD233 0 0 0
ISOD233 3 67.5 22.5
DASD23 4 88 22
*/
return ;
}
7.12
就知道这题有坑。
prog1.cpp: In constructor 'Sales_data::Sales_data(std::istream&)':
prog1.cpp::: error: 'read' was not declared in this scope
read(is, *this);
翻了一下收藏的博客,发现这道题要用友元函数(下一小节)。
7.13
参考(不会写)。
Sales_data total(cin);
if (total.units_sold > ) {
Sales_data trans;
while (read(cin, trans)) {
if (total.isbn() == trans.isbn())
total.combine(trans);
else {
print(cout, total) << endl;
total = trans;
}
}
print(cout, total) << endl;
} else {
cerr << "No data?!" << endl;
}
7.14
是这样吗?
Sales_data()
{
units_sold = ;
revenue = 0.0;
}
7.15
测试无误。
// constructor
Person() = default;
Person(const string &name): name(name) {}
Person(const string &name, const string &address): name(name), address(address) {}
Person(istream&);
Person::Person(istream &is)
{
read(is, *this);
}
【拷贝、赋值和析构】
如果我们不主动定义这些操作,那么编译器将会替我们合成它们。
默认的析构函数将会在语句块结束时被调用,销毁局部变量。
某些类(管理动态内存的类)不能依赖于合成的版本,因此有时候不得不定义这些函数。
【c++ primer, 5e】构造函数 & 拷贝、赋值和析构的更多相关文章
- [c++基础]3/5原则--拷贝构造函数+拷贝赋值操作符
/* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> #include &qu ...
- 构造函数和初始化表、this指针与常函数、析构函数、拷贝构造与拷贝赋值(day05)
十四 构造函数和初始化表 ... 初始化表 )语法形式 class 类名{ 类名(形参表):成员变量1(初值),...{} }; )必须要使用初始化表的场景 -->如果有类 类型的成员变量,而该 ...
- C++类中函数(构造函数、析构函数、拷贝构造函数、赋值构造函数)
[1]为什么空类可以创建对象呢? 示例代码如下: #include <iostream> using namespace std; class Empty { }; void main() ...
- C++中的构造函数,拷贝构造函数和赋值运算
关于C++中的构造函数,拷贝构造函数和赋值运算,以前看过一篇<高质量C++/C编程指南>的文章中介绍的很清楚,网上能搜索到,如果想详细了解这方面的知识可以参看一下这篇文章. 常见的给对象赋 ...
- 关于C++中的拷贝构造函数和赋值函数
如果类定义的数据成员中存在指针或引用,那么最好重载这两个函数. 1. 定义 拷贝构造函数的定义格式:构造函数名(const 源类名& 引用对象形参名){} 赋值函数定义格式:源类名 & ...
- C++雾中风景6:拷贝构造函数与赋值函数
在进行C++类编写的过程之中,通常会涉及到类的拷贝构造函数与类的赋值函数.初涉类编写的代码,对于两类函数的用法一直是挺让人困惑的内容.这篇文章我们会详细来梳理拷贝构造函数与赋值函数的区别. 1.调用了 ...
- C++中:默认构造函数、析构函数、拷贝构造函数和赋值函数——转
对于一个空类,编译器默认产生4个成员函数:默认构造函数.析构函数.拷贝构造函数和赋值函数.1.构造函数:构造函数是一种特殊的类成员,是当创建一个类的时候,它被调用来对类的数据成员进行初始化和分配内存. ...
- 【C++】拷贝构造函数和赋值符函数
在C++中,调用拷贝构造函数有三种情况: 1.一个对象作为函数参数,以值传递的方式传入函数体. 2.一个对象作为函数返回值,以值传递的方式从函数返回. 3.一个对象用于给另外一个对象进行初始化(复制初 ...
- CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数
类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数 // person.h #ifndef _PERSON_H_ #define _PERSON_H_ class Person{ public : ...
随机推荐
- vue2.0非父子间进行通讯
在vue中,父组件向之组件通讯使用的是props,子组件向父组件通讯使用的是$emit+事件,那非父子间的通讯呢,在官方文档上只有寥寥数笔, 概念很模糊,这个空的vue实例应该放在哪里呢,光放文档并没 ...
- 如何使用phpmyadmin建立外键约束
之前都是用sql语句进行的主外键的关联,现在用可视化的phpmyadmin感觉方便了很多,但是在做主外键约束的时候却十中找不到操作在哪里.网上搜索的也是千奇百怪五花八门的,都说的很晦涩,很多都说需要使 ...
- flex布局,input点击软键盘激活,底部按钮上移
安卓手机的问题,原本表单没有超出一屏的时候,上移的现象也是存才的,只是需要滑动body才能看得到,现在,超出一屏了,现象就很明显了 body明显上移: 点击input修改价格: 软键盘出现: 先尝试了 ...
- node sever
一.基础创建服务器 // 引入Http var http = require("http"); // 创建服务器 http.createServer(function(reques ...
- 进击的RecyclerView入门一(简单上手)
虽然RecyclerView面世有一段时间了,但由于它的学习成本相对较高,很多码友只是粗略的认识了一下而没有细致的品味RecyclerView的真谛. 那么从现在开始我将带你装逼带你飞,一起领略Goo ...
- django post 403解决之道(最新版Django)
写了一个方法,丢出一个post请求,发现报403 百度解决方案: 按提示及google结果修改setting.py,在MIDDLEWARE_CLASSES增加django.middleware.csr ...
- odex反编译dex异常 Cannot locate boot class path file /system/framework/core.odex
为了将ROM中system/app下的CertInstaller.odex反编译为CertInstaller.dex,输入命令: "java -jar baksmali.jar -x C ...
- php 安装yaf扩展和yaf框架
一.安装yaf扩展(windows安装) 1.查看你电脑安装的开发环境(phpinfo()的信息),查找 "Zend Extension Build"和"PHP Exte ...
- Java8 新特性之Stream API
1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...
- Linux ssh服务
关于ssh服务不多说就提几句,1,机房的服务器一般都是通过远程连接登录的,远程登录就必然少不了ssh客户端.2,虚拟机每次都要点击进去,每次退出来也需要按Ctrl+Alt+Enter,也比较麻烦,有时 ...