-
C++对象数组作为类成员的问题
2013-11-23 18:37:49//对象数组作为类的成员 } 那样的话对象数组的初始化会变得很麻烦, 因为数组名不能作为左值,所以不可以指针传递的方式赋值。 而且不能通过参数列表(构造函数后面加一个冒号)的方式初始化, 所以只能让类...例如:
class ObjectB{};
class ObjectA{
public:
ObjectB array[5];//对象数组作为类的成员
}
那样的话对象数组的初始化会变得很麻烦,
因为数组名不能作为左值,所以不可以指针传递的方式赋值。
而且不能通过参数列表(构造函数后面加一个冒号)的方式初始化,
所以只能让类ObjectA自动调用类ObjectB的无参构造函数.
---------------#include <iostream.h>
#include "stdlib.h"
class ObjectB{
public:
int a;
public:
ObjectB(int m=0)
{
a=m;
}
};
class ObjectA{
public:
ObjectB Array[5];
public:
ObjectA(int *p)
{
Array[0]=ObjectB(p[0]);
Array[1]=ObjectB(p[1]);
Array[2]=ObjectB(p[2]);
}
};
int main()
{
int p[5]={0,2,2,3,4};
ObjectA am=ObjectA(p);
cout<<am.Array[1].a<<endl;
return 0;
}
---------------
我们可以使用替代方式:
class A{};
classB{
public:
A*a;//A类型的指针作为类的成员
}
同样带来很大的问题,
(1)浅拷贝,深拷贝的问题,除非重载拷贝构造函数,类B才能实现深拷贝,因为成员中有指针,所以无法简单的用拷贝构造函数生成一个新对象,而用无参构造函数生成的新对象也会有问题,因为里面的指针一般都默认为NULL了。
重载拷贝构造函数的时候需要申请一定长度的内存,将拷贝对象的指针所指向的空间拷贝到新申请的空间,再进行操作。注意申请后要释放。
一个拷贝构造函数的例子
SparseMatrix::SparseMatrix(const SparseMatrix&s)
{
Rows=s.Rows;
Cols=s.Cols;
Count=s.Count;
smArray=new Trituple[6];
//此处还需要复制对象
}
----------------------
补充知识:
------------------http://www.ksarea.com/articles/20070829_memory-partition-stack-heap-difference.htmlC/C++应该是大学里最先接触的编程语言,它们的重要性不言而喻。但是我始终抱着“数组名就是指针”的错误信条到现在,可能是因为大学老师错误的讲解使我一直保留着这种误解。指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用,所以也难免在学习中将两者混淆。这里介绍下指针和数组名的区别:
1.指针和数组名占据的内存空间大小不一样,如下程序1:
char str[10];
char *pstr=str;
cout<<
cout<<sizeof
第一行输出结果是:10,第二行输出结果是:4从这里我们可以看出:数组名对应着(而不是指向)一块内存(数组所占的内存区域)或者说是指代数组这种数据结构,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针对应着一个占据4个字节(Win32)的内存区域,而指向这4个字节所存储的地址所对应的内存单元,它可以指向任意类型的内存块。因此,sizeof(str)值为数组占据的内存空间大小即10个字节,而sizeof(pstr)值为指针的值占据的内存空间大小即4个字节。
2.数组名不是指针,但是在一定的情况下转换为指代数组的首地址的指针,而这个数组名转为的指针只能是指针常量。
在以下两种情况下才能进行这种转换:
a.在程序1第二行代码中,将数组名直接赋值给指针,此时数组名转换为指向数组的首单元的常量指针。
b.直接将数组名作为指针形参的时候,数组名则转换为指向数组的首单元的常量指针进行传递,如下程序2:
void fun(char str[])
{
cout<<
str++;
}
void main()
{
…
char str1[5];
fun(str1);
…
}
注意:数组名作为函数形参进行传递时,在子函数体内,它已经不再是一个指针常量,而是变成一个真正的指针,可以进行增减等操作,可以被修改。所以程序2中子程序第一条语句输出的sizeof(str)的值为4.既然数组名可以被看作指针常量,而常量是不能修改的,那么如下代码是不允许的:
char str[10];
str++;
但如下代码则合法的:
char str[10];
char *pstr=str;
pstr++;
3.使用指针访问数组和使用数组名访问数组本质不同。
例如:
char str[7]=”ksarea”;
char *pstr=str;
cout<<<
其中str[3]和pstr[3]返回的都是字符’r',但是编译器产生的执行代码却不一样。对于str[3],执行代码是从str开始,向后移动两个字节,然后取出其中的字符;而对于pstr[3],执行代码是从pstr中取出地址,然后在其上加3,然后取出对应内存中的字符。当然,如果pstr是指向int型的指针,那么pstr[3]的处理过程是从pstr中取出地址,然后在其上加上3*sizeof(int),最后取出对应内存中的字符,其他的数据类型一次类推。 -
C++数组作为类的私有成员求助
2015-11-22 05:36:28定义一个Employee类,其中包括姓名、街道地址、城市和邮编等属性,...在主程序中定义这个类的对象并对其进行操作。 请问下构造函数如果设置了形参那要怎么实现?还有就是strcpy()函数要怎么使用啊...QAQ跪求大神指点 -
C++笔记(22)——this指针、对象数组、类作用域
2020-07-19 15:34:26类的每一个成员函数都有一个this指针,该指针指向调用成员函数的对象,被作为隐藏参数传递给成员函数。在成员函数的括号后面加const限定符时,无法通过this指针修改对象的值。 使用示例:比较两个对象数据成员的...1、this指针
类的每一个成员函数都有一个this指针,该指针指向调用成员函数的对象,被作为隐藏参数传递给成员函数。在成员函数的括号后面加const限定符时,无法通过this指针修改对象的值。
使用示例:比较两个对象数据成员的大小时,程序无法直接访问对象数据,可以通过成员函数,成员函数返回值到程序中再比较。也可以设计一个成员函数,可以访问两个对象的数据,但需要第二个对象作为参数(即成员函数的参数为该类的一个对象),如下图:
2、对象数组
声明像普通数组一样,形式如下:
Stock mystuff[4];
未显式初始化对象,调用默认函数。也可以显式初始化,如下:
Stock stocks[2]={Stock("name1",22.2,10),Stock("name2",22.6,23)};
先用默认函数构造数组,然后花括号中的构造函数创建临时对象,然后将临时对象的内容复制到相应的元素中。
3、类作用域
类中成员名(包括数据和函数)的作用域为整个类,即只在类内知道,类外不可知,所以不同的类中可以使用相同的成员名,调用公有部分时通过对象。
(1)作用域为类的常量
在类的声明中不可const int m=1;这样直接定义常量,因为类在声明时没有创建对象,还没有分配存储空间。处理方法有下面两种:
①使用枚举,声明时不会创建类数据成员,且所有对象中都不包含枚举。
class Bakery
{
private:
enum {m=8};
double cost[m];
...
}
②使用关键字static,该常量将和其他静态存储变量存在一起,而不存储在对象中。
class Bakery
{
private:
static const int m=8;
double cost[m];
...
}
(2)作用域内枚举
-
C++ day17 类(三) this指针,对象数组
2020-03-15 22:13:35文章目录this指针(指向调用成员函数的对象,即类方法都给this指针存储了调用自己的对象的地址)示例 比较两个对象的成员的值对象数组(每一个元素都是一个对象)示例 求一个对象数组中某成员值最大的对象this指针在...文章目录
this指针(指向调用成员函数的对象,即类方法都给this指针存储了调用自己的对象的地址)
this指针被作为隐藏参数传递给了类方法,有了它,在方法内部就可以使用调用该方法的对象了
每个成员函数,包括构造函数和析构函数,都有一个this指针,指向调用这个方法的对象,好让方法知道是谁在调用自己,如果自己内部代码需要使用调用自己的对象,也有办法称呼这个对象(*this就是调用此方法的对象的别名啦)
const成员函数的this指针也是const的,即不能使用this指针修改对象的值
如果方法需要显式地引用调用它的对象,就要用this指针。this指针指向调用对象的地址,所以*this是调用对象的别名。
示例 比较两个对象的成员的值
如果要比较两个对象的成员的值的大小,那么需要用到2个对象,之前写的代码全部都只用了一个对象,但是我们并不需要像以前那样,把两个对象都作为参数传给方法,而是只需要传其中一个,另一个对象来调用这个方法,很棒吧,返回二者中某成员更大的一个对象
那这里说了要把对象作为参数和返回值传递,那么怎么传呢?之前说过了,要传递引用。即把对象的引用作为方法的参数和返回值,这样使用的仍是对象本身,不是副本,却无需笨拙复制。
再者,进一步考虑,前面说了,如果成员函数不修改对象的值,则尽量设计为const成员函数,这里只是比较,当然不会修改,所以理应设计为const的。并且之前学习按引用传参时强调了,一般都尽量把引用形参和返回值设计为const的。
综上两点,我们的比较方法的原型里需要三个const。//原型 const Stock & Stock::topval(const Stock & s) const; //定义 const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; }
如果没有this指针,那上面定义中最后一句代码,你抓破脑袋也不知该返回啥能表示你返回的是调用此函数的对象的引用
上面代码的total_val,以及之前代码的构造函数中直接写各个数据成员的名字,其实都是相当于把this->total_val中的this指针和间接成员运算符省略了而已
代码:
//stock.h #ifndef STOCK_H_ #define STOCK_H_ #include <string> class Stock //类声明 class declaration //一个常见但不通用的约定:类名首字母大写 { private://可不写,类对象的默认访问控制就是private std::string company; long shares; double share_val; double total_val; //可以在成员函数中使用数据成员 //定义位于类声明中的函数自动成为内联函数,无需关键字inline void set_tot(){total_val = shares * share_val;} public: Stock(const std::string & co, long n, double pr);//构造函数 Stock();//默认构造函数 ~Stock();//析构函数destructor void buy(long num, double price); void sell(long num, double price); void update(double price); void show() const; const Stock & topval(const Stock & s) const; };//像结构体声明一样,有分号 #endif // STOCK_H_
//Stock.cpp #include <iostream> #include "stock.h" //构造函数没有返回值,参数的数目和类型根据类的私有成员确定 Stock::Stock(const std::string & co, long n, double pr) { //千万不要把构造函数的形参名称设置为和类数据成员一样 //否则会出现company = company;的错误语句 std::cout << "Constructor using " << co << " called.\n"; company = co; if (n < 0) { std::cerr << "Number of shares can't be negative; " << company << " shares set to 0.\n"; shares = 0; } else shares = n; share_val = pr; set_tot(); } //默认构造函数 Stock::Stock() { company = "no name"; shares = 0; share_val = 0.0; total_val = 0.0; std::cout << "Default constructor called.\n"; } //析构函数 Stock::~Stock() { std::cout << "Bye! " << company << "\n"; } //类的成员函数的定义都必须用作用域解析运算符标识函数所属的类 void Stock::buy(long num, double price) { //增加持有的股份 if (num < 0) { std::cout << "Number of shares purchased can't be nagative. " << "Transaction is aborted.\n"; } else { shares += num; share_val = price; set_tot(); } } void Stock::sell(long num, double price) { //减少持有的股份 if (num <0) { std::cout << "Number of shares sold can't be negative. " << "Transaction is aborted.\n"; } else if (num > shares) { std::cout << "You can't sell more than you have! " << "Transaction is aborted!\n"; } else { shares -= num; share_val = price; set_tot(); } } void Stock::update(double price) { share_val = price; set_tot(); } void Stock::show() const { using std::cout; using std::ios_base; //set format to #.### ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield); std::streamsize prec = cout.precision(3); cout << "Company: " << company << " Shares: " << shares << '\n' << " Share Price: $" << share_val; //set format to #.## cout.precision(2); cout << " Total Worth: $" << total_val << '\n'; //restore original format cout.setf(orig, ios_base::floatfield); cout.precision(prec); } const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; }
#include <iostream> #include "stock.h" int main() { //为了看清析构函数被调用,所以在return之前弄个块 { using std::cout; const Stock stock1 = {"NanoSmart", 12, 20.0}; stock1.show(); const Stock stock2 = {"World Cabbages", 100, 2.0}; stock2.show(); const Stock a1 = stock1.topval(stock2); const Stock a2= stock2.topval(stock1); a1.show(); a2.show(); }//自动调用析构函数,清理对象 return 0; }
上面函数中的cerr是ostream类的另一个对象,把输出发送到标准错误流。
Constructor using NanoSmart called. Company: NanoSmart Shares: 12 Share Price: $20.000 Total Worth: $240.00 Constructor using World Cabbages called. Company: World Cabbages Shares: 100 Share Price: $2.000 Total Worth: $200.00 Company: NanoSmart Shares: 12 Share Price: $20.000 Total Worth: $240.00 Company: NanoSmart Shares: 12 Share Price: $20.000 Total Worth: $240.00 Bye! NanoSmart Bye! NanoSmart Bye! World Cabbages Bye! NanoSmart
对象数组(每一个元素都是一个对象)
之前觉得结构数组很牛逼,对象数组和结构数组很相似,还更高级
对象数组的每一个元素都是一个对象,初始化对象数组时可以对每个对象使用不同的构造函数
可以只初始化前一部分的对象元素,剩余的则使用默认构造函数初始化最常用的初始化对象数组的方案:
先用默认构造函数创建数组元素
再用花括号中的构造函数创建临时对象,再把临时对象们的内容复制到相应的对象中,这要求必须为类写默认构造函数示例 求一个对象数组中某成员值最大的对象
//stock.h #ifndef STOCK_H_ #define STOCK_H_ #include <string> class Stock //类声明 class declaration //一个常见但不通用的约定:类名首字母大写 { private://可不写,类对象的默认访问控制就是private std::string company; long shares; double share_val; double total_val; //可以在成员函数中使用数据成员 //定义位于类声明中的函数自动成为内联函数,无需关键字inline void set_tot(){total_val = shares * share_val;} public: Stock(const std::string & co, long n, double pr);//构造函数 Stock();//默认构造函数 ~Stock();//析构函数destructor void buy(long num, double price); void sell(long num, double price); void update(double price); void show() const; const Stock & topval(const Stock & s) const; };//像结构体声明一样,有分号 #endif // STOCK_H_
//Stock.cpp #include <iostream> #include "stock.h" //构造函数没有返回值,参数的数目和类型根据类的私有成员确定 Stock::Stock(const std::string & co, long n, double pr) { //千万不要把构造函数的形参名称设置为和类数据成员一样 //否则会出现company = company;的错误语句 std::cout << "Constructor using " << co << " called.\n"; company = co; if (n < 0) { std::cerr << "Number of shares can't be negative; " << company << " shares set to 0.\n"; shares = 0; } else shares = n; share_val = pr; set_tot(); } //默认构造函数 Stock::Stock() { company = "no name"; shares = 0; share_val = 0.0; total_val = 0.0; std::cout << "Default constructor called.\n"; } //析构函数 Stock::~Stock() { std::cout << "Bye! " << company << "\n"; } //类的成员函数的定义都必须用作用域解析运算符标识函数所属的类 void Stock::buy(long num, double price) { //增加持有的股份 if (num < 0) { std::cout << "Number of shares purchased can't be nagative. " << "Transaction is aborted.\n"; } else { shares += num; share_val = price; set_tot(); } } void Stock::sell(long num, double price) { //减少持有的股份 if (num <0) { std::cout << "Number of shares sold can't be negative. " << "Transaction is aborted.\n"; } else if (num > shares) { std::cout << "You can't sell more than you have! " << "Transaction is aborted!\n"; } else { shares -= num; share_val = price; set_tot(); } } void Stock::update(double price) { share_val = price; set_tot(); } void Stock::show() const { using std::cout; using std::ios_base; //set format to #.### ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield); std::streamsize prec = cout.precision(3); cout << "Company: " << company << " Shares: " << shares << '\n' << " Share Price: $" << share_val; //set format to #.## cout.precision(2); cout << " Total Worth: $" << total_val << '\n'; //restore original format cout.setf(orig, ios_base::floatfield); cout.precision(prec); } const Stock & Stock::topval(const Stock & s) const { if (s.total_val > total_val) return s; else return *this; }
#include <iostream> #include "stock.h" const int STKS = 4; int main() { //为了看清析构函数被调用,所以在return之前弄个块 { using std::cout; Stock ar[STKS] = { Stock("NanoSmart", 120, 2.5), Stock(), Stock("World Cabbage", 130, 1.25), Stock("Sherry Games", 452, 1.35) }; cout << "Stock holdings:\n"; int i; for (i = 0; i < STKS; ++i) ar[i].show();//非const对象也可以使用show函数 const Stock * top = &ar[0]; for (i = 0; i < STKS; ++i) top = &top->topval(ar[i]);//->的优先级大于& cout << "\nThe most valuable holding:\n"; top->show(); }//自动调用析构函数,清理对象 return 0; }
Constructor using NanoSmart called. Default constructor called. Constructor using World Cabbage called. Constructor using Sherry Games called. Stock holdings: Company: NanoSmart Shares: 120 Share Price: $2.500 Total Worth: $300.00 Company: no name Shares: 0 Share Price: $0.000 Total Worth: $0.00 Company: World Cabbage Shares: 130 Share Price: $1.250 Total Worth: $162.50 Company: Sherry Games Shares: 452 Share Price: $1.350 Total Worth: $610.20 The most valuable holding: Company: Sherry Games Shares: 452 Share Price: $1.350 Total Worth: $610.20 Bye! Sherry Games Bye! World Cabbage Bye! no name Bye! NanoSmart
this指针在C中的样子
如果把C++的有this指针的代码转换为C代码,那么就要显式把this作为参数传给函数(C++的每个类方法都隐式传了this指针的),并且在构造函数中都要用间接成员运算符才可以使用到调用当前函数的对象的数据成员。
总结 (OOP真香)
通过到目前对类的学习可以发现,主要的工作是类的设计上,即大部分时间精力都是在写类方法,只有少部分时间用于写主函数,且主函数只是为了测试类设计的是否正确合理。并且每次变更需求,增加需求,都只需要改类设计的实现代码,大部分东西都不需要改,仍然可以使用,真香
-
C++实验6 对象数组
2020-04-10 07:57:16(2)学习如何在类中内嵌对象数组成员变量。 (3)学习对象数组的初始化。 2 实验内容 2.1 根据题目要求编写模拟的程序 (1)五一小假期,许多人选择外出旅游。每位乘客(Passenger)最多可以 携带 3 件行李...实验六 对象数组
1 实验目的
(1)学习如何使用数组名作为函数的参数,通过传数组的方式,在被调用
函数中访问主调函数中的多个对象的方法。
(2)学习如何在类中内嵌对象数组成员变量。
(3)学习对象数组的初始化。 2 实验内容2.1 根据题目要求编写模拟的程序
(1)五一小假期,许多人选择外出旅游。每位乘客(Passenger)最多可以
携带 3 件行李(Luggage)。并且乘客可以选择个人自由行;或者参加旅行社
(TravelAgency)组织的旅行团。
(2)自由行的目的地、旅行团的目的地都相同,都是 3 个,分别是国内短 途(DomesticShort)、国内长途(DomesticLong)和国际游(International)。用枚
举类型表示。
(3)旅行社总共安排了 5 个旅行团(Team),旅行团的目的地类型不限。每
个团最多允许 6 位游客报名。超过 6 位,就不再加入新的游客了。
(4)自由行的乘客需要到售票处(TicketOffice)亲自买票(Ticket);参加
旅行团的乘客,由旅行团到售票处团购。国内短途票 10 元/位,国内长途 100 元/ 位,国际票 500 元/位。购买国际票时,每位乘客可以免费托运 2 件行李。超过 2 件,每件行李多收 100 元托运费。
(5)模拟乘客到旅行社报名,自由行乘客到售票处买票,以及旅行社统一
到售票处团购票的过程。3 2.题目要求
(1)创建新的工程项目 HolidayTravel;
(2)主程序对应的源文件名为 main.cpp,里面包含 main()函数。
(3)乘客名字的合法命名规则是“乘客 A”,……,“乘客 Z”;“乘客 a”,……,
“乘客 z”;“乘客 0”,……,“乘客 9”。最多可以自动生成 62 位乘客。
(4)编写程序并测试
可以自由定义类的成员,可以自由扩展程序,只要实现题目要求即可。
(5)程序执行完毕后,命令行窗口显示的结果可能是:
我是乘客 A,选择自由出行,国内长途,携带 2 件行李,行李编号是 A01、 A02,买票需付 100 元。 我是乘客 B,报名旅行社,选择国内短途,携带 3 件行李,行李编号是 B01、 B02、B03,买票需付 10 元。 我是乘客 C,报名旅行社,选择国际游,携带 3 件行李,行李编号是 C01、 C02、C03,买票需付 500 元,行李托运费 100 元。
……
……
旅行社开始报名。
旅行社共计安排了 5 个旅行团,共计××人报名。
出行的目的地分别是:…,…,…,…,…;每个旅行团的人数分别
是:…,…,…,…,…;每个旅行团需要支付的票价是:…,…,…,…,…。
售票处开始售票。
售票结束,营业额统计信息如下:
国内短途自由行:……元,乘客姓名:………………
国内长途自由行:……元,乘客姓名:………………
国际游自由行: ……元,乘客姓名:………………
国内短途团购: ……元,乘客姓名:………………
国内长途团购: ……元;乘客姓名:………………
国际游团购: ……元;乘客姓名:………………提示:采用下面的方法产生随机数,并根据随机数的不同,生成不同类型的乘客(出行的目的地、携带的行李、个人自由行,或跟随旅行社出游)。
#include <ctime> // For time() #include <cstdlib> // For srand() and rand() const int MAX_TYPE = ***; srand(static_cast<unsigned> (time(NULL))); // 初始化随机数发生器 int number = rand(); int remainder = number % MAX_TYPE;
源代码
#include <iostream> #include <string> #include <ctime> #include <cstdlib> #include <iomanip> using namespace std; class Luggage; class Passenger; class Team; class TicketOffice; class Ticket; enum TravelType {Single, Team}; enum Destination { DomesticShort, DomesticLong, International}; class Luggage { public: Luggage(string code = "") : code(code) { } void setLuggageCode(string code) { this->code = code; } string getLuggageCode() { return code; } private: string code; }; class Passenger { public: Passenger() { } Passenger(int travelTypeRand, int destinationRand, int luggageNumberRand) { string letter = ""; if (count < 26) { letter += count + 'A'; // static_cast<char>(count + 'A'); } else if (count < 52) letter += static_cast<char>(count - 26 + 'a') ; else if (count < 62) letter += static_cast<char>(count - 52 + '0'); name = "乘客" + letter; travelType = static_cast<TravelType>(travelTypeRand % 2); destination = static_cast<Destination>(destinationRand % 3); luggageNum = luggageNumberRand % 4; for (int i = 0; i < luggageNum; i++) { char suffix = i + '1'; luggages[i].setLuggageCode(letter + '0' + suffix); } count++; } Passenger(string name, TravelType travelType, Luggage luggages[], int luggageNum) : name(name), travelType(travelType), luggageNum(luggageNum) { for (int i = 0; i < luggageNum; i++) this->luggages[i] = luggages[i]; count++; } void buyTicket(TicketOffice &office); Destination getDestination() { return destination; } TravelType getTravelType() { return travelType; } string getName() { return name; } int getLuggageNum() { return luggageNum; } Ticket * getTicket() { return ticket; } void setTicket(Ticket *ticket) { this->ticket = ticket; } void showInfo() { cout << "我是" << name << "," << TRAVEL_TYPE_TEXT[travelType]; cout << "," << DESTINATION_TEXT[destination]; cout << ",携带" << luggageNum << "件行李"; if (luggageNum > 0) { cout << ",行李编号是"; for (int i = 0; i < luggageNum; i++) cout << luggages[i].getLuggageCode() << "、"; cout << "\b\b"; } cout << ",买票需付" << FARE_TEXT[destination] << "。"; if (destination == International && luggageNum > 2) { cout << "\b\b,行李托运费" << 100 * (luggageNum - 2) << "元。"; } cout << endl; } private: string getDestinationText() { return DESTINATION_TEXT[destination]; } string getTravelTypeText() { return TRAVEL_TYPE_TEXT[travelType]; } static const int MAX_LUGGAGE_NUM = 4; static int count; static const string TRAVEL_TYPE_TEXT[2]; static const string DESTINATION_TEXT[3]; static const string FARE_TEXT[3]; static const int FARE[3]; Luggage luggages[MAX_LUGGAGE_NUM]; string name; TravelType travelType; Destination destination; int luggageNum; Ticket *ticket; }; int Passenger::count = 0; const string Passenger::TRAVEL_TYPE_TEXT[2] = { "选择自由出行", "报名旅行社" }; const string Passenger::DESTINATION_TEXT[3] = { "国内短途", "国内长途", "国际旅游" }; const string Passenger::FARE_TEXT[3] = { "1O元", "100元", "500元" }; const int Passenger::FARE[3] = { 10, 100, 500 }; class TravelTeam { public: TravelTeam(int destinationRand = 0) : count(0), teamFare(0) { destination = static_cast<Destination>(destinationRand % 3); } Destination getDestination() { return destination; } int getCount() { return count; } void setDestination(int destinationRand) { destination = static_cast<Destination>(destinationRand % 3); } bool addMember(Passenger &passenger) { if (count < MAX_PASSENGER_NUM) { passengers[count] = passenger; count++; return true; } else return false; } Passenger & getMember(int index) { return passengers[index]; } bool isFull() { return count >= MAX_PASSENGER_NUM; } int getTeamFare() { return teamFare; } void setTeamFare(int teamFare) { this->teamFare = teamFare; } private: static const int MAX_PASSENGER_NUM = 6; Destination destination; Passenger passengers[MAX_PASSENGER_NUM]; int count; int teamFare; }; class Ticket { public: void setTicket(Destination destination, double fare) { this->destination = destination; this->fare = fare; } private: Destination destination; double fare; }; class TravelAgency { public: TravelAgency(TravelTeam teams[], int size); bool registerMember(Passenger &passenger); void buyTicket(TicketOffice &office); void showInfo(); private: static const string DESTINATION_TYPE_TEXT[3]; int teamNum; TravelTeam *teams; }; const string TravelAgency::DESTINATION_TYPE_TEXT[3] = { "国内短途", "国内长途", "国际旅游" }; TravelAgency::TravelAgency(TravelTeam teams[], int size) { teamNum = size; this->teams = teams; } bool TravelAgency::registerMember(Passenger &passenger) { bool isSuccessful = false; for (int i = 0; i < teamNum; i++) { if (passenger.getDestination() == teams[i].getDestination()) { if (!teams[i].isFull()) { teams[i].addMember(passenger); isSuccessful = true; break; } else continue; } } return isSuccessful; } void TravelAgency::showInfo() { int totalNum = 0; for (int i = 0; i < teamNum; i++) { totalNum += teams[i].getCount(); } cout << "旅行社共计安排了5个旅行团,共计" << totalNum << "人报名。" << endl; cout << "出行的目的地分别是:"; for (int i = 0; i < teamNum; i++) { cout << DESTINATION_TYPE_TEXT[teams[i].getDestination()] << ","; } cout << "\b\b;" << endl << "每个旅行团的人数分别是:"; for (int i = 0; i < teamNum; i++) { cout << teams[i].getCount() << ","; } cout << "\b\b;" << endl << "每个旅行团需要支付的票价是:"; for (int i = 0; i < teamNum; i++) { cout << teams[i].getTeamFare() << ","; } cout << "\b\b。" << endl; } class TicketOffice { public: TicketOffice(int ticketNum) : ticketNum(ticketNum), count(0), totalIncome(0) { tickets = new Ticket[ticketNum]; } ~TicketOffice() { delete[] tickets; } void personalCharge(Passenger &passenger, int fare); int teamCharge(TravelTeam &team); void showInfo(); private: Ticket *tickets; int ticketNum; int count; double totalIncome; double personalIncome[3]; double teamIncome[3]; string personalPassengerNames[3]; string teamPassengerNames[3]; static const string DESTINATION_TYPE_TEXT[3]; static const int FARE[3]; }; const string TicketOffice::DESTINATION_TYPE_TEXT[3] = { "国内短途", "国内长途", "国际旅游" }; const int TicketOffice::FARE[3] = { 10, 100, 500 }; void Passenger::buyTicket(TicketOffice &office) { if (travelType == Single) { int fare = FARE[destination]; if (destination == International && luggageNum > 2) { fare += 100 * (luggageNum - 2); } office.personalCharge(*this, fare); } } void TravelAgency::buyTicket(TicketOffice &office) { for (int i = 0; i < teamNum; i++) { //int teamFare = FARE[teams[i].getDestination()] * teams[i].getCount();/// int teamFare = office.teamCharge(teams[i]); teams[i].setTeamFare(teamFare); } } void TicketOffice::personalCharge(Passenger &passenger, int fare) { Destination destination = passenger.getDestination(); TravelType travelType = passenger.getTravelType(); if (travelType == Single) { totalIncome += fare; personalIncome[destination] += fare; personalPassengerNames[destination] += passenger.getName() + ","; tickets[count].setTicket(destination, fare); // 为售票处的第count张票指定目的地、票价等信息 passenger.setTicket(&tickets[count]); // 把售票处的第count张票绑定到当前的乘客上 count++; } } int TicketOffice::teamCharge(TravelTeam &team) { Destination destination = team.getDestination(); int baseFare = FARE[destination]; int teamBaseFare = baseFare * team.getCount(); int teamFare = teamBaseFare; teamIncome[destination] += teamBaseFare; totalIncome += teamBaseFare; for (int i = 0; i < team.getCount(); i++) { Passenger &passenger = team.getMember(i); int luggageFee = 0; teamPassengerNames[destination] += passenger.getName() + ","; if (destination == International && passenger.getLuggageNum() > 2) { luggageFee = 100 * (passenger.getLuggageNum() - 2); teamFare += luggageFee; teamIncome[destination] += luggageFee; totalIncome += luggageFee; } tickets[count].setTicket(destination, baseFare + luggageFee); passenger.setTicket(&tickets[count]); count++; } return teamFare; } void TicketOffice::showInfo() { for (int i = 0; i < 3; i++) { cout << DESTINATION_TYPE_TEXT[i] << "自由行:" << setw(4) << personalIncome[i] << "元,乘客姓名:" << personalPassengerNames[i] << endl; } for (int i = 0; i < 3; i++) { cout << DESTINATION_TYPE_TEXT[i] << "团购: " << setw(4) << teamIncome[i] << "元,乘客姓名:" << teamPassengerNames[i] << endl; } cout << "收入总计:" << totalIncome << "元。" << endl; } int main(int argc, char *argv[]) { const int MAX_PASSENGER_NUM = 62; const int MAX_TEAM_NUM = 5; srand(static_cast<unsigned>(time(NULL))); // 初始化随机数发生器 int passengerNum = rand() % MAX_PASSENGER_NUM; cout << passengerNum << endl; Passenger **passengers = new Passenger*[passengerNum]; for (int i = 0; i < passengerNum; i++) { int travelTypeRand = rand(); int destinationRand = rand(); int luggageNumberRand = rand(); passengers[i] = new Passenger(travelTypeRand, destinationRand, luggageNumberRand); passengers[i]->showInfo(); } cout << endl << "旅行社开始报名。" << endl; TravelTeam teams[MAX_TEAM_NUM]; for (int i = 0; i < MAX_TEAM_NUM; i++) { teams[i].setDestination(rand()); } TravelAgency agency(teams, MAX_TEAM_NUM); for (int i = 0; i < passengerNum; i++) { if(passengers[i]->getTravelType() == Team) agency.registerMember(*passengers[i]); } agency.showInfo(); cout << endl << "售票处开始售票。" << endl; TicketOffice office(MAX_PASSENGER_NUM); for (int i = 0; i < passengerNum; i++) passengers[i]->buyTicket(office); agency.buyTicket(office); cout << "售票结束,营业额统计信息如下:" << endl; office.showInfo(); for (int i = 0; i < passengerNum; i++) delete passengers[i]; delete[] passengers; return 0; }
-
对象作为类的成员变量的程序设计
2016-09-27 01:02:37对象作为类的成员变量的程序设计。设计类Student和类Date, 其中Student的成员变量birthday是date类的对象,类Student的其他成员和类Date的成员按常规设计,特别要注意两个类的构造函数设计;在主函数中利用对象数组... -
类的数组成员变量的初始化
2010-12-14 19:05:00这里介绍一下当数组作为类的成员变量时,应该怎么对它(数组)进行初始化。 在类的构造函数中可以使用成员初始化表初始化各个成员变量,这种方法是很受推荐和赞扬的,因为使用成员初始化表中对成员进行初始化和在... -
C++实验三:抽象与分类(数组作为函数参数的冒泡排序、求组合数、构造函数析构函数)
2020-10-22 09:14:224、掌握类的定义、类对象定义、赋值和基本访问方法,学习类的成员函数。 5、掌握用指针访问类的方法,学习类的访问权限控制。 6、掌握类的构造函数和析函数的原理和使用。 实验内容 1、传递一个数组作为函数... -
C++初始化列表问题,类中有一个对象类型的数组成员变量,在初始化列表中初始化时报错“[]”操作符语法错误
2013-03-12 15:10:22有两种变通方案:你可以把对象数组改成指针数组,或者把ClassB类的构造和初始化分开。 方案一: class ClassA{ private: ClassB* arrayOfObjectClassB[2]; public: ClassA(int i){ arrayObjectOfCl -
Java 方法引用:通过对象名、类名、super、this、类的构造器、数组的构造器引用
2020-05-27 22:35:02文章目录方法引用1、语法引用符2、通过对象名引用成员方法3、通过类名称引用静态方法4、通过super引用成员方法5、通过this引用成员方法6、类的构造器引用7、数组的构造器引用 方法引用 1、语法引用符 双冒号::为... -
C++学习笔记 数组对象
2011-03-27 01:35:00在类中可以使用数组,也可以将数组作为类的对象 a.直接在声明数组对象的时候初始化对象成员 #include<iostream><br />using namespace std; class area { public: ... -
es6 遍历数组对象获取所有的id_ES6系列【第三弹】教你看清set和map
2021-01-01 16:57:37关于Set它类似于数组,但是其成员的值都是唯一的,没有重复的值(甚至在Set内部,NaN和NaN是相等的)它在初始化的时候接受一个数组或者类数组作为参数,数组里的值将会做为set的成员:初始化之后我们就得到了一个set,... -
数组详解
2020-07-13 19:12:541、数组是一种引用类型,数组作为对象,数组中的元素作为对象的属性,数组还包括一个成员属性 length。 2、创建数组,其实相当于创建了一个对象,数组对象存放在堆内存中。 3、数组这种数据结构优缺点? 优点:检索... -
C++第十章__类和对象定义的基础知识__类的构造函数和析构函数__const成员函数__书中的构造函数和析构函数的...
2019-09-27 02:00:18目录 类和对象定义的基础知识 ...对象数组&this指针 一起使用的一个例程 类作用域 作用域为类的常量(在类中定义常量) 类似栈的C++实现方法 类和对象定义的基础知识 //通过一个例子来说... -
Java中的数组
2016-03-28 14:54:57Java中数组作为一个特殊的类,其操作基本数据类型和引用数据类型的方式各不相同。Java数组本省属于引用数据类型,每一个数组实例都是一个对象,这些对象同属于一个类。 Java数组的本质是一个类,该类还保存了数据... -
(一四六)包含对象成员的类——第十四章
2016-02-21 17:04:29一个类对象,可以是另一个类的成员。就像string类可以作为其他类的类成员一样。 valarray类: valarray类是一个模板类,模板类可以处理不同的数据类型。 其头文件是: 使用和声明方式类似vector类和array类。 ... -
day3-2020-7-20 数组 面向对象
2020-07-20 20:24:03Day3 2020-7-20数组获取数组长度面向对象面向对象和面向过程类和对象类成员变量和局部变量面向对象三大特征之封装This关键字构造方法 数组 是一种容器可以存放多个变量 特点 一种引用类型 数组中类型必须一样 数组... -
java学习之路 之 面向对象编程-数组练习题(2)
2016-07-29 22:28:59(1)定义类Pritimive,在类中定义一个有3个元素的boolean类型的数组t作为其成员变量。数组元素未赋值。 */ public class Primtive { private boolean[] t = new boolean[3]; public Primtive() { } ... -
数组去重和字符串去重的几种简单方法
2020-02-28 19:49:10初始化 Set 可以接受一个数组或类数组对象作为参数,也可以创建一个空的 Set 初始化传入要去重的数组,转换成Set类型, 再使用…三个点扩展运算符和用数组包起来重新组成新的数组或 使用Array.from(),把类数组转换... -
java——数组
2019-10-04 02:02:22数组变量是引用类型变量,数组能够作为对象,数组中的每个元素相当于对象的成员变量,所以数组元素能够默认初始化。(博客java——变量分类有关于成员变量初始化的说明)。 一维数组 声明 type var[];或者... -
Java日常总结:构造方法手写;...引用数据类型作为成员属性;引用数据类型作为数组元素;
2020-08-05 12:57:461.构造方法需要写出来...如果get和set方法中除了有赋值和取值逻辑,还有其他其他逻辑,那么,推荐在构造方法中,通过this.get/set()的形式操作属性,以免初始化对象的过程中错失验证过程 3.bean类,需要提供一个返回 -
C++类中成员变量的初始化总结二
2020-05-24 14:47:35C++类中成员变量的初始化总结一三种成员变量初始化位置对于类的成员对象的初始化成员数组的初始化基本类型的成员数组对象成员数组补充一下动态数组的初始化vector作为成员变量的初始化 C++类中成员变量的初始化总结... -
JAVA习题--数组1
2019-05-16 19:57:48JAVA习题–数组 1.(1)定义类Pritimive,在类中定义一个有3个元素的boolean类型的数组t...(2)给对象d的成员变量t赋值为{true,true,true},并输出t的三个元素值。 练习目的:检验基本数据类型数组创建时的自动赋值。 ... -
java学习之类的成员方法
2019-04-15 20:05:38java学习之类的成员方法类的成员方法语法代码示例传入一个参数传入多个参数数组作为参数传入对象作为参数传入 类的成员方法 语法 访问修饰符 返回类型 方法名(形式参数列表){ //方法主体 } 代码示例 无参的... -
剑指offer——把数组排成最小的数C++
2020-12-28 00:50:46全部转为字符串存入数组,对其进行sort即可。 主要是cmp函数比较难写 ...同时静态成员函数不可以调用类的非静态成员。 C++中的字符串可以直接比较大小,cmp比较的结果,决定了排序方式(升序或者降. -
JavaScript一行代码实现数组去重
2020-07-27 20:17:06Set 是一个构造函数,用来生成 Set 数据结构,它类似于数组,但是成员的值都是唯一的、没有重复的, 初始化 Set 可以接受一个数组或类数组对象作为参数,也可以创建一个空的 Set: new Set( 数组 ),返回一个去重后... -
把数组排成最小的数
2019-10-05 14:38:511用全排列 再遍历去比较哪个小这个...因为:非静态成员函数是依赖于具体对象的,而std::sort这类函数是全局的,因此无法再sort中调用非静态成员函数。 静态成员函数或者全局函数是不依赖于具体对象的,可以独立访问... -
c++类和对象实验报告.docx
2020-12-21 23:31:49实验一 类和对象 实验课程名面向对象程序设计 C++ 专业...掌握对象数组对象指针和string 类的使用方法 掌握使用对象对象指针和对象引用作为函数参数的方法 掌握类对象作为成员的使用方法 掌握静态数据成员和静态成员
-
程序员必修基础套餐课
-
美图大数据平台架构实践
-
M1 芯片Macbook pro连接支持AirPrint的佳能打印机
-
使用Jenkins搭建iOS/Android持续集成打包平台
-
结合使用电纺丝和微成型来调节雪旺氏细胞行为,制备取向聚己内酯支架
-
全光子晶体光纤单级直接放大产生34 W高功率飞秒脉冲
-
MacOS M1关于ltp(python)的使用
-
UL 153:2020 Portable Electric Luminaires(便携灯具)- 最新完整英文版(204页)
-
美团外卖Android平台化架构演进实践
-
2021-02-25
-
Vue中的动画封装(5-7)
-
LVS + Keepalived 实现 MySQL 负载均衡与高可用
-
docker基本使用教程, 以及docker部署flask框架示例
-
大数据多维分析引擎在魅族的实践
-
项目经理成长之路
-
Python下划线命名模式 - 小结(转载)
-
gdbinit
-
百亿级日志系统架构设计及优化
-
PPT大神之路高清教程
-
使用 Linux 平台充当 Router 路由器