《absolute C++》7.1 ,7.2笔记

《absolute C++》 

Constructors and Other Tools

---------------------------------------------------------------------------------------------------------------------------

Tip1:构造函数不能像成员函数那样调用,也没有返回值

 

date1.DayOfYear(7, 4); //VERY ILLEGAL
date2.DayOfYear(5, 5); //VERY ILLEGAL

♦ 像这样调用构造函数是非法的,

Tip2: 构造函数的初始化段

DayOfYear::DayOfYear(int monthValue, int dayValue)
                : month(monthValue), day(dayValue)
{/*Body intentionally empty*/}

♦构造函数在类外被定义,定义在参数列表后与函数定义前

♦构造函数的初始化段成员变量名在圆括号外,(即month,day)成员变量的初始值,也就是我们想要赋给成员变量的值放在括号里,初始化值可以是构造函数的参数值,正如本例。

♦也就是说,month(monthValue), day(dayValue)语句等同于month=monthValue; day=dayValue; 也就是说,我们习惯定义构造函数为

DayOfYear::DayOfYear(int monthValue, int dayValue)
{
month = monthValue;
day = dayValue;
}

而这与我们使用初始化段但函数体为空的构造函数效果一致。

♦ 使用了初始化段的构造函数的函数体可以不为空(事实上也常常不为空),可以用来检测赋值正确与否,比如:

DayOfYear::DayOfYear(int monthValue, int dayValue)
                : month(monthValue), day(dayValue)
{
        if ((month < 1) || (month > 12))
            {
                cout << "Illegal month value!\n";
                exit(1);
            }
        if ((day < 1) || (day > 31))
            { 
                cout << "Illegal day value!\n";
                exit(1);
             }
}

Tip3: 默认构造函数与构造函数的显式调用

♦ 如果想用无参数构造构造函数来初始化对象(date3)的时候,是不加括号的。

DayOfYear date1(2, 21), date2(5), date3;

♦ 如果你声明了一个带括号的无参数构造函数,会造成歧义。

DayOfYear date3()

编译器会认为你定义了一个函数名为date3,返回值为DayOfYear类类型的函数。

♦ 除了在声明对象时,会自动调用构造函数(必须给定相应的参数),构造函数也可以被显式调用,

Variable = Constructor_Name(Arguments_For_Constructor);

holiday = DayOfyear(10, 31)

♦ 但对象holoday必须事先已经被声明

♦ 在C++中,具体的流程是,构造函数DayOfYear先构造了一个匿名对象,用来存储10月31号,然后将该匿名对象赋值给对象holiday。在这里,构造函数的行为类似于返回一个类型为本身,数值为显式声明的函数。

无参数构造函数函数的显式调用后面必须包含圆括号!

holiday = DayOfYear( );

Tip4:在定义构造函数后,默认的无参构造函数将不存在

所以,建议在定义的所有类中,都定义一个默认的无参数的构造函数。用来产生一个未初始化的对象。

SampleClass::SampleClass( )
{/*Do nothing.*/}

Tip5:类类型成员变量的构造函数声明

例:

Holiday::Holiday(int month, int day, bool theEnforcement)
           : date(month, day), parkingEnforcement(theEnforcement)
 {/*Intentionally empty*/}


类holiday的成员变量date是一个类类型的成员变量, 这样在holiday类(外层类)的构造函数定义中,参数列表必须包含date类的所有成员变量,而初始化段则直接声明使用date类的构造函数,本类(holiday)独有的成员变量则照常初始化。

Tip6:在初始化段中调用函数(Display 7.2的难点解释)

有些情况中,需要对初始化成员变量的参数值进行一定的运算,需要调用函数,这个时候可直接将函数使用在初始化段中。正如BankAccount程序中,如果用户直接声明一个double类型的balance,而不是分别用int变量表示账户余额的元部分与分部分,这个时候就需要用函数来分离这个double类型的balance,从而将分离出来的值分别初始化accountDollars和accountCents两个成员变量。使用语法如下:

BankAccount::BankAccount(double balance, double rate)
                     : accountDollars(dollarsPart(balance)), accountCents(centsPart(balance))
            {
             setRate(rate);
             }

♦本例的另外几点说明: ① BankAccount的构造函数主要目的就是初始化accountDollars,accountCents和rate这三个成员变量,如果用户分别输入两个int类型的值(即账户余额的元部分与分部分)和一个double类型的值,则不需要分离函数。正如另外一个构造函数所示的那样:

BankAccount::BankAccount(int dollars, int cents, double rate)

{
   setBalance(dollars, cents);
    setRate(rate);
 }

♦ 本例的这个构造函数没有使用初始化段,而是使用了set函数来初始化dollars和cents,事实上这也是可以的,并且set函数还可以写入检查部分(即检查输入的值是否符合要求)

为了使得解释完整,下列set函数的代码段:

void BankAccount::setBalance(int dollars, int cents)

{     if ((dollars < 0 && cents > 0) || (dollars > 0 && cents < 0) )   // 检查段

      {
         cout << "Inconsistent account data.\n";
        exit(1);
       }
  accountDollars = dollars;    // 赋值段 ,可以发现这里将参数dollars,cents赋值给了成员变量 accountDollars ,accountCents 
  accountCents = cents;
 }

void BankAccount::setRate(double newRate)
 {
   if (newRate >= 0.0)
  rate = newRate;          //赋值段 ,可以发现这里将参数newRate赋值给了成员变量rate
  else
      {
           cout << "Cannot have a negative interest rate.\n";  // 这里将检查段放在了后面
           exit(1);
      }
 }

Tip7:const修饰参数和这么做的理由

 因为在调用一个结构或者类类型的形参的时候,如果使用传值(不加&),在效率上会有所降低,所以推荐使用引用调用(加&),这两种方式在代码的实现上没有区别,区别是

①:引用调用效率更高

②:引用调用会改变参数值,所以使用const来设定不改变参数值。

传值调用方式:

bool isLarger(BankAccount account1, BankAccount account2)
     //Returns true if the balance in account1 is greater than that
     //in account2. Otherwise returns false.
 {
    return(account1.getBalance( ) > account2.getBalance( ));
 }

引用调用方式:const放最前

bool isLarger(const BankAccount& account1, const BankAccount& account2)

//Returns true if the balance in account1 is greater than that
//in account2. Otherwise, returns false.
{
return(account1.getBalance( ) > account2.getBalance( ));
}

Tip8:const修饰成员函数和这么做的理由

♦有些成员函数不需要改变成员变量,如output等成员函数,修饰词const可以用来限定调用对象不可修改(包含对象里的所有成员变量)标记成员函数时,const方放最后,这与const修饰参数不同。

函数在类内的声明:

class BankAccount
{
public:
...
void output( ) const;
...

函数在类外的定义:

void BankAccount::output( ) const
{
...

}

Tip9:const使用的连贯性

♦如果使用了const修饰了一个类类型的参数,那么所有不会改变调用对象值的成员函数都需要用const来修饰,如output成员函数调用了一个声明为const的类类型参数,那么output的声明也应该使用const来修饰。

Tip10:静态成员函数与静态数据成员

1.静态数据成员实际上是类域中的全局变量。所以,静态数据成员的定义(初始化)不应该被放在头文件中。不要试图在头文件中定义(初始化)静态数据成员。在大多数的情况下,这样做会引起重复定义这样的错误。即使加上#ifndef #define #endif或者#pragma once也不行。

2.静态数据成员被 类 的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。

♦所有静态成员变量的初始化应该在类定义之外,并且一个静态成员变量不能初始化两次。初始化方法如下:

int Server::turn = 0;
int Server::lastServed = 0;
bool Server::nowOpen = true;

♦static只在静态成员函数的声明中用到(类内),而在该成员函数的定义中则不再出现

时间: 2024-10-10 23:33:58

《absolute C++》7.1 ,7.2笔记的相关文章

HTML+CSS笔记 CSS进阶再续

CSS的布局模型 清楚了CSS 盒模型的基本概念. 盒模型类型, 我们就可以深入探讨网页布局的基本模型了.布局模型与盒模型一样都是 CSS 最基本. 最核心的概念. 但布局模型是建立在盒模型基础之上,又不同于我们常说的 CSS 布局样式或 CSS 布局模板.如果说布局模型是本,那么 CSS 布局模板就是末了,是外在的表现形式. CSS包含3种基本的布局模型,用英文概括为:Flow.Layer 和 Float. 在网页中,元素有三种布局模型:1.流动模型(Flow)2.浮动模型 (Float)3.

【锋利的JQuery-学习笔记】Tab选项卡的实现

效果图: 关键点: 1.标签和标签内容都是用<ul><li>实现的,主要是通过Css样式设计成选项卡的模样. 2.用js代码实现点击标签时,标签内容的切换(做法是<div id="jnBrandList">横向滚动). html: <div id="jnBrand"> <div id="jnBrandTab"> <h2 title="品牌活动">品牌活动&

《CSS网站布局实录》学习笔记(三)

第三章 CSS网页布局与定位 3.1 div 几乎XHTML中的任何标签都可以用于浮动与定位,而div首当其冲.对于其他标签而言,往往有它自身存在的目的,而div元素存在的目的就是为了浮动与定位. 3.1.1 div是什么 div是XHTML中制定的.专门用于布局设计的容器对象.在传统表格式布局中,之所以能够进行页面的排版布局设计,完全依赖于表格对象table.如今,接触另一种布局方式--CSS布局.div正是这种布局方式的核心对象.仅从div的使用上说,做一个简单的布局只需要依赖两样东西:di

CSS学习笔记09 简单理解BFC

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>BFC</title> 6 <style type="text/css"> 7 .div1 {background-color: #FCE38A; width: 200px; height: 100px;}

&lt;转&gt;字符编码笔记:ASCII,Unicode和UTF-8

本文转自:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思路.但是,我尽量试图写得通俗易懂,希望能对其他朋友有用.毕竟,字符编码是计算机技术的基石,想要熟练使用计算机,就必须懂得一点字符编码的知识. 1. ASC

js练习题笔记

javascrip测试题: 一.选择题(每题2分,多选题错选.少选不得分) 1.分析下段代码输出结果是( )    var arr = [2,3,4,5,6];    var sum =0;    for(var i=1;i < arr.length;i++) {        sum +=arr[i]    }    console.log(sum);A.20     B.18     C.14     D.12 2.以下关于 Array 数组对象的说法不正确的是(  )A.对数组里数据的排序

Sass学习笔记之入门篇

Sass又名SCSS,是CSS预处理器之一,,它能用来清晰地.结构化地描述文件样式,有着比普通 CSS 更加强大的功能. Sass 能够提供更简洁.更优雅的语法,同时提供多种功能来创建可维护和管理的样式表.以下是我的学习笔记. Sass安装环境 1.安装sass(mac) ①:Ruby安装 ②:安装sass sudo gem install sass 可以通过 sass -v检测是否完成安装   2.更新sass gem update sass 3.卸载(删除)sass gem uninstal

字符编码笔记:ASCII,Unicode和UTF-8(转载)

作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步搞清楚. 下面就是我的笔记,主要用来整理自己的思路.但是,我尽量试图写得通俗易懂,希望能对其他朋友有用.毕竟,字符编码是计算机技术的基石,想要熟练使用计算机,就必须懂得一点字符编码的知识. 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)

HTML+CSS笔记--1

(初接触html+css时一些笔记) 1.父盒子的高可以不用给,让里面的内容撑起来就好. 2.对于外边距合并问题,解决方法overflow : hidden;,或者是另外加一个边框可以下来. 3.对于网站的logo,我们要给它设置关键字,写在a元素里, 1 .logo a{ 2 display: block; 3 height: 40px; 4 text-indent: -2000em;/*首行缩进 em是一个字的大小,rem是以一个根的大小 这个字是给搜索引擎看的*/ 5 } 4.我们可以将具