使用struct关键字定义类

使用class和struct定义类的唯一区别就是默认的访问权限

  • 使用struct关键字,定义在第一个访问说明符之前的成员是public
  • 使用class关键字,定义在第一个访问说明符之前的成员是private

定义在类内的成员函数是自动inline的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include<cstring>
#include<iostream>
using namespace std;

struct Sales_data{
/*
- isbn成员函数用于返回对象的ISBN编号
- combine成员函数,用于将一个Sales_data对象加到另一个对象上
- avg_price成员函数,用于返回售出书籍的平均价格
*/
string isbn() const{return bookNo;}//这是一个常量成员函数,不能改变调用它的对象的内容
Sales_data& combine(const Sales_data&);
double avg_price() const;

string bookNo; //ISBN
unsigned units_sold = 0; //销售总数
double revenue = 0.0; //收益
};

double Sales_data::avg_price() const
{
if(units_sold)
return revenue/units_sold;
else
return 0;
}

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;//返回调用该函数的对象
}

/*
* Salse_data的非成员接口函数:
- add函数,执行两个Sales_data对象的加法
- read函数,将数据从istream读入到Sales_data对象中
- print函数,将Sales_data对象的值输出到ostream
*/
Sales_data add(const Sales_data& ,const Sales_data&);
ostream &print(ostream& , const Sales_data&);
istream &read(istream& , const Sales_data&);

//输入的交易信息包括ISBN、售出总数、售出价格
istream &read(istream &is, Sales_data &item)
{
double price = 0.0;
is>>item.bookNo>>item.units_sold>>price;
}
ostream &print(ostream &os, const Sales_data &item)
{
os<<item.isbn()<<" "<<item.units_sold<<" "
<<item.revenue<<" "<<item.avg_price();
return os;
}

Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;//把lhs的数据成员拷贝给sum
sum.combine(rhs);
return sum;
}

int main()
{
Sales_data total;
string temp;
temp = "shansan";
total.bookNo = temp;
//total.bookNo = "shansan";
cout<<total.bookNo<<endl;
cout<<total.isbn()<<endl;
return 0;
}

使用=default保留默认的构造函数 & 构造函数初始值列表

  • 当我们需要其他构造函数的时,同时也希望保留默认的构造函数时候,可以使用= default
  • 构造函数初始值是成员函数的一个列表,每个名字后面紧跟括号括起来的(或则在花括号内的)成员初始值。不同成员的初始值通过逗号分隔
  • 构造函数初始值列表只说明用于初始化成员的值,而不限定初始化的具体执行顺序
  • 但是如果一个成员是用另一个成员来初始化的,那么这两个成员的初始化顺序就很重要
  • consturctor(parameter):initializer_list,注意那个冒号,构造函数不能被声明成const的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include<cstring> 
#include<iostream>
using namespace std;

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) {}
//声明一个constructor,定义放在类外了
Sales_data(istream&);


string isbn() const{return bookNo;}//这是一个常量成员函数,不能改变调用它的对象的内容
Sales_data& combine(const Sales_data&);
double avg_price() const;

string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};


double Sales_data::avg_price() const
{
if(units_sold)
return revenue/units_sold;
else
return 0;
}

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;//返回调用该函数的对象
}

/*
* Salse_data的非成员接口函数:
- add函数,执行两个Sales_data对象的加法
- read函数,将数据从istream读入到Sales_data对象中
- print函数,将Sales_data对象的值输出到ostream
*/
Sales_data add(const Sales_data& ,const Sales_data&);
ostream &print(ostream& , const Sales_data&);
istream &read(istream& , const Sales_data&);

//输入的交易信息包括ISBN、售出总数、售出价格
istream &read(istream &is, Sales_data &item)
{
double price = 0.0;
is>>item.bookNo>>item.units_sold>>price;
}
ostream &print(ostream &os, const Sales_data &item)
{
os<<item.isbn()<<" "<<item.units_sold<<" "
<<item.revenue<<" "<<item.avg_price()<<endl;
return os;
}

Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;//把lhs的数据成员拷贝给sum
sum.combine(rhs);
return sum;
}

//类外定义新的构造函数
Sales_data::Sales_data(istream &is)
{
read(is,*this);//从is中读入一条信息存到this对象中
}

int main()
{
Sales_data total;//调用默认的构造函数
string temp;
temp = "shansan";
total.bookNo = temp;
//total.bookNo = "shansan";
cout<<total.bookNo<<endl;
cout<<total.isbn()<<endl;

Sales_data let("shansan.top",33,33);//调用构造函数Sales_data(const string &s, unsigned n, double p)
cout<<let.bookNo<<" "<<let.units_sold<<" "<<let.revenue<<endl;

Sales_data read_print;//调用默认的构造函数
read(cin,read_print);
print(cout,read_print);

Sales_data dada(cin);//调用构造函数Sales_data(istream &is)
print(cout,dada);

return 0;
}

委托构造函数

  • 一个委托构造函数使用它所属类的其他构造函数执行它自己的初始化过程
  • 它把自己的一些或全部职责委托给了其他构造函数
  • 一个委托构造函数和其他构造函数一样也有一个成员初始值列表和一个函数体
  • 委托构造函数的成员初始值列表只有一个入口,就是类名本身。类名后面紧跟圆括号括起来的初始值列表,参数列表必须与另一个构造函数匹配
  • 当一个构造函数委托给另一个构造函数时,受委托的构造函数的初始值列表和函数体被依次执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
using namespace std;

class People{
public:
//非委托构造函数使用对应的实参初始化成员
People(string m,string x,int n):first_name(m),last_name(x),age(n) {}

//其余构造函数全部委托给另一个构造函数
//注意使用冒号
People(): People("li","lei",18){}
People(string insert): People(insert,"wan",33){}
People(int a): People("wu","ge",a){}

int print_info(People temp)
{
cout<<temp.first_name<<" "<<temp.last_name<<" "<<temp.age<<endl;
return 0;
}
private:
string first_name;
string last_name;
int age;
};

int main()
{
People num_1("shan","san",18);//调用构造函数 People(string m,string x,int n)
num_1.print_info(num_1);

People num_2;//调用委托构造函数 People("li","lei",18)
num_2.print_info(num_2);

People num_3("six");//调用委托构造函数 People(string insert)
num_3.print_info(num_3);

People num_4(100);//调用委托构造函数 People(int a)
num_4.print_info(num_4);
return 0;
}


 评论


博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 , 总访问量为 次 。