定义抽象数据类型初探this和12345678910structSales_data{string isbn(){returnbookNo;}Sales_data combine(constSales_data);doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0;};Sales_data total;引入this对于isbn成员函数的调用 total.isbn();当我们调用成员函数时实则上是在替某个对象调用它。在上面的调用中当isbn返回bookNo时实际上隐式地返回total.bookNo.成员函数通过一个名为this的额外隐式参数来访问调用它的那个对象。当我们调用一个成员函数时用请求该函数的对象地址初始化this。例如如果调用total.isbn(),编译器负责把total的地址传递给isbn的隐式形参this可以等价认为编译器将该调用重写成Sales_data::isbn(total),调用Sales_data时的isbn成员时传入了total的地址。在成员函数内部我们可以直接使用调用该函数的对象的成员而无须通过成员访问运算符来做到这一点因为this所指的正是这个对象。任何对类成员的直接访问都被看做this的隐式调用例如isbn在使用bookNo时隐式地使用this指向的成员就如同this-bookNo一样。构造函数定义类通过一个或几个特殊的成员函数来控制其对象的初始化这些函数叫做构造函数。无论何时只要类的对象被创建就会执行构造函数。构造函数的名字和类名一样构造函数没有返回类型一个类可以拥有多个构造函数但每个构造函数之间必须在参数数量或参数类型上存在不同。且构造函数不能被声明成const。当一个类没有定义任何构造函数时编译器会给类自动添加一个默认构造函数该构造函数无须任何实参对对象进行初始化。对前面的Sales_data类进行编写构造函数12345678910111213structSales_data{Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}(1)default的含义如果需要默认构造函数起作用那么可以在参数列表后面写上default来要求编译器生成默认构造函数。(2)构造函数初始值列表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(const string s):bookNo(s),units_sold(0),revenue(0)();访问控制和封装访问控制符public和private定义在public说明符之后的成员在整个程序可被访问。定义在private说明符之后的成员可以被类的成员函数访问但是不能被使用该类的代码访问。Sales_data类的新形式123456789101112131415classSales_data{public:Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);private:doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}友元类允许其他类或者函数访问他的非公有成员方法是令其他类或者函数成为他的友元。如果一个类想把一个函数作为他的友元只需要增加一个friend关键字开始的函数声明语句即可123456789101112131415161718classSales_data{friendSales_data add(constSales_data ,constSales_data);friendistream read(istream,Sales_data);friendostream print(ostream,constSales_data)public:Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);private:doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}友元的声明只能出现在类定义的内部。友元不是类的成员也不受他所在区域访问控制级别的约束。类的其他特性可变数据成员在一个const成员函数中若希望修改类的某个数据成员可以通过在变量的声明中加入mutable关键字实现12345678910classscreen{public:voidsome_menmber()const;private:mutablesize_taccess_ctr};voidscreen::some_member()const{access_ctr}返回*this的成员函数12345678910111213141516inlineScreen Screen::set(charc){contents[cursor]c;return*this;}inlineScreen Screen::set(pos r,pos col,charch){contents[r*widthcol]ch;return*this;}inlineScreen Screen::move(pos r,pos c){pos rowr*width;cursorrowc;return*this;}move和set一样返回的值是对对象的引用。myScreen.move(4,0).set(#)等同于myScreen.move(4.0);myScreen.set(#);假如我们定义的返回类型不是引用则move的返回值将是*this的副本因此调用set只能改变临时副本不能改变myScreen的值友元类例如window_mgr类的某些成员需要访问screen类的内部数据例如window_mgr的clear函数将一个指定的screen类的内容设置为空白。
C++ primer类的基础精讲
定义抽象数据类型初探this和12345678910structSales_data{string isbn(){returnbookNo;}Sales_data combine(constSales_data);doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0;};Sales_data total;引入this对于isbn成员函数的调用 total.isbn();当我们调用成员函数时实则上是在替某个对象调用它。在上面的调用中当isbn返回bookNo时实际上隐式地返回total.bookNo.成员函数通过一个名为this的额外隐式参数来访问调用它的那个对象。当我们调用一个成员函数时用请求该函数的对象地址初始化this。例如如果调用total.isbn(),编译器负责把total的地址传递给isbn的隐式形参this可以等价认为编译器将该调用重写成Sales_data::isbn(total),调用Sales_data时的isbn成员时传入了total的地址。在成员函数内部我们可以直接使用调用该函数的对象的成员而无须通过成员访问运算符来做到这一点因为this所指的正是这个对象。任何对类成员的直接访问都被看做this的隐式调用例如isbn在使用bookNo时隐式地使用this指向的成员就如同this-bookNo一样。构造函数定义类通过一个或几个特殊的成员函数来控制其对象的初始化这些函数叫做构造函数。无论何时只要类的对象被创建就会执行构造函数。构造函数的名字和类名一样构造函数没有返回类型一个类可以拥有多个构造函数但每个构造函数之间必须在参数数量或参数类型上存在不同。且构造函数不能被声明成const。当一个类没有定义任何构造函数时编译器会给类自动添加一个默认构造函数该构造函数无须任何实参对对象进行初始化。对前面的Sales_data类进行编写构造函数12345678910111213structSales_data{Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}(1)default的含义如果需要默认构造函数起作用那么可以在参数列表后面写上default来要求编译器生成默认构造函数。(2)构造函数初始值列表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(const string s):bookNo(s),units_sold(0),revenue(0)();访问控制和封装访问控制符public和private定义在public说明符之后的成员在整个程序可被访问。定义在private说明符之后的成员可以被类的成员函数访问但是不能被使用该类的代码访问。Sales_data类的新形式123456789101112131415classSales_data{public:Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);private:doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}友元类允许其他类或者函数访问他的非公有成员方法是令其他类或者函数成为他的友元。如果一个类想把一个函数作为他的友元只需要增加一个friend关键字开始的函数声明语句即可123456789101112131415161718classSales_data{friendSales_data add(constSales_data ,constSales_data);friendistream read(istream,Sales_data);friendostream print(ostream,constSales_data)public:Sales_data()default;Sales_data(conststring s):bookNo(s)()Sales_data(conststring s,unsigned n,doublep):bookNo(s),units_sold(n),revenue(p*n){}Sales_data(istream )string isbn()const{returnbookNo;}Sales_data combine(constSales_data);private:doubleavg_price()const;string bookNo;unsigned units_sold0;doublerevenue0.0;}友元的声明只能出现在类定义的内部。友元不是类的成员也不受他所在区域访问控制级别的约束。类的其他特性可变数据成员在一个const成员函数中若希望修改类的某个数据成员可以通过在变量的声明中加入mutable关键字实现12345678910classscreen{public:voidsome_menmber()const;private:mutablesize_taccess_ctr};voidscreen::some_member()const{access_ctr}返回*this的成员函数12345678910111213141516inlineScreen Screen::set(charc){contents[cursor]c;return*this;}inlineScreen Screen::set(pos r,pos col,charch){contents[r*widthcol]ch;return*this;}inlineScreen Screen::move(pos r,pos c){pos rowr*width;cursorrowc;return*this;}move和set一样返回的值是对对象的引用。myScreen.move(4,0).set(#)等同于myScreen.move(4.0);myScreen.set(#);假如我们定义的返回类型不是引用则move的返回值将是*this的副本因此调用set只能改变临时副本不能改变myScreen的值友元类例如window_mgr类的某些成员需要访问screen类的内部数据例如window_mgr的clear函数将一个指定的screen类的内容设置为空白。