C++ primer类的基础精讲
2026/6/2 8:02:50 网站建设 项目流程

定义抽象数据类型

初探this和

1

2

3

4

5

6

7

8

9

10

structSales_data

{

string isbn(){returnbookNo;}

Sales_data & combine(constSales_data&);

doubleavg_price()const;

string bookNo;

unsigned units_sold=0;

doublerevenue=0;

};

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类进行编写构造函数

1

2

3

4

5

6

7

8

9

10

11

12

13

structSales_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_sold=0;

doublerevenue=0.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类的新形式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

classSales_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_sold=0;

doublerevenue=0.0;

}

友元

类允许其他类或者函数访问他的非公有成员,方法是令其他类或者函数成为他的友元。如果一个类想把一个函数作为他的友元,只需要增加一个friend关键字开始的函数声明语句即可

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

classSales_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_sold=0;

doublerevenue=0.0;

}

友元的声明只能出现在类定义的内部。友元不是类的成员,也不受他所在区域访问控制级别的约束。

类的其他特性

可变数据成员

在一个const成员函数中,若希望修改类的某个数据成员,可以通过在变量的声明中加入mutable关键字实现

1

2

3

4

5

6

7

8

9

10

classscreen{

public:

voidsome_menmber()const;

private:

mutablesize_taccess_ctr

};

voidscreen::some_member()const

{

++access_ctr

}

返回*this的成员函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

inlineScreen &Screen::set(charc)

{

contents[cursor]=c;

return*this;

}

inlineScreen &Screen::set(pos r,pos col,charch)

{

contents[r*width+col]=ch;

return*this;

}

inlineScreen &Screen::move(pos r,pos c)

{

pos row=r*width;

cursor=row+c;

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类的内容设置为空白。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询