码迷,mamicode.com
首页 > 编程语言 > 详细

《absolute C++》7.1 ,7.2笔记

时间:2015-05-30 20:57:54      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

《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只在静态成员函数的声明中用到(类内),而在该成员函数的定义中则不再出现

 

《absolute C++》7.1 ,7.2笔记

标签:

原文地址:http://www.cnblogs.com/tianye/p/4540473.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!