C++Primer13.4节练习

练习13.33:

成员save是将本Message存放在给定的Folder中,成员remove是删除本Message,save/remove会调用insert函数/erase函数,如果不使用引用,直接使用Folder作为形参,那么save和remove中修改的是Folder的副本,函数运行结束,副本被释放,没有改变任何东西。由于需要删除对应Folder中的Message指针,即对Folder进行修改,所以不能使用const Folder&

练习13.34:

对Message进行定义,未定义Folder

#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <algorithm>
#include <set>

class Folder;
class Message {
	friend class Folder;
	friend void swap(Message& lhs, Message& rhs);
public:
	//folders被隐式初始化为空集合
	explicit Message(const std::string& str = ""):contents(str){ }
	//拷贝构造成员,用来管理指向本Message的指针
	//拷贝构造函数
	Message(const Message&);
	//拷贝赋值运算符
	Message& operator=(const Message&);
	~Message();
	//从给定Folder集合中添加/删除本Message
	void save(Folder&);
	void remove(Folder&);


private:
	//消息内容
	std::string contents;
	//包含message的Folder的set
	std::set<Folder*>folders;
	//拷贝构造函数,拷贝赋值运算符和析构函数所使用的工具函数
	//将Message添加到指向参数的Folder中,Folder指向传递的参数,进行了拷贝,要添加一个Message进去,也就是本Message
	void add_to_Folders(const Message&);
	//从folders中的每一个Folder中删除Message,此Message是此对象的Message
	void remove_from_Folders();
};

class Folder {
public:
	void addMsg(Message* m);
	void remMsg(Message* m);
};


void Message::save(Folder& f)
{
	//将给定的Folder添加到我们的Folder列表中
	folders.insert(&f);
	//将本Message添加到f的Message集合中
	f.addMsg(this);
}

void Message::remove(Folder& f)
{
	//将给定Folder从我们的Folder列表中删除
	folders.erase(&f);
	//将本Message从f的Message集合中删除
	f.remMsg(this);
}

//将本Message添加到指向m的Folder中
void Message::add_to_Folders(const Message& m)
{
	//遍历每个包含m的Folder
	for (auto f : m.folders)
	{
		//向每个Folder中添加一个指向本Message的指针
		f->addMsg(this);
	}
}

//Message的拷贝构造函数拷贝给定对象的数据成员
Message::Message(const Message& m) :contents(m.contents), folders(m.folders)
{
	//拷贝构造完成后将本消息添加到指向m的Folder中
	add_to_Folders(m);
}

//从对应的Folder中删除本Message
void Message::remove_from_Folders()
{
	//遍历本Message中的所有Folder,把指向本Message的指针删除
	for (auto f : folders)
	{
		f->remMsg(this);
	}
}

//析构函数
Message::~Message()
{
	remove_from_Folders();
}


//拷贝赋值运算符
Message& Message::operator=(const Message& rhs)
{
	//先从左侧运算对象的folders中删除此Message的指针,然后再将指针添加到右侧运算对象的folders中
	remove_from_Folders();
	contents = rhs.contents;
	folders = rhs.folders;
	//将本Message添加到那些Folder中
	add_to_Folders(rhs);
	return *this;
}

//自定义的swap
void swap(Message& lhs, Message& rhs)
{
	using std::swap;
	//将每个消息的指针从它所在的Folder中删除
	for (auto f : lhs.folders)
	{
		f->remMsg(&lhs);
	}

	for (auto f : rhs.folders)
	{
		f->remMsg(&rhs);
	}

	//交换contents和Folder指针set
	swap(lhs.contents, rhs.contents);
	//交换set&
	swap(lhs.folders, rhs.folders);

	//将每个Message的指针添加到它的(新)Folder中
	for (auto f : lhs.folders)
	{
		f->addMsg(&lhs);
	}


	for (auto f : rhs.folders)
	{
		f->addMsg(&rhs);
	}
}


int main()
{
	
	system("pause");
	return 0;
}

练习13.35:

Message成员中,contents为string类型,folders为set类型,标准库中都有自己的拷贝控制成员,对于这两个成员,使用合成的拷贝控制也能实现拷贝。但是拷贝完成后,我们还需要将拷贝后的Message添加到对应的Folder中,无法使用合成的版本来实现,需要我们自己定义

练习13.36:

Folder类实现如下:


//与Message基本类似,两者是对称的
class Folder {
	friend class Message;
	friend void swap(Message& lhs, Message& rhs);
public:
	//默认构造函数
	Folder(){ };
	//拷贝构造函数
	Folder(const Folder& f);
	//拷贝赋值运算符
	Folder& operator=(const Folder& f);
	//析构函数
	~Folder();
	//Folder版本的save和remove函数
	void save(Message&);
	void remove(Message&);


private:
	std::set<Message*>msg;
	//与Message类似的两个添加删除工具函数
	void add_to_Message(const Folder&);
	void remove_from_Message();
	//向msg中添加或删除一个给定的Message*
	void addMsg(Message* m);
	void remMsg(Message* m);
};

//向msg中添加或删除一个给定的Message*
void Folder::addMsg(Message* m)
{
	msg.insert(m);
}

void Folder::remMsg(Message* m)
{
	msg.erase(m);
}

//save成员函数
void Folder::save(Message& m)
{
	msg.insert(&m);
	//将本Folder添加到m的Folder集合中
	m.addFolder(this);
}

//remove成员函数
void Folder::remove(Message& m)
{
	msg.erase(&m);
	//将本Folder从m的Folder集合中删除
	m.remFolder(this);
}

//将本Folder添加到指向f的Message中
void Folder::add_to_Message(const Folder& f)
{
	for (auto m : f.msg)
	{
		m->addFolder(this);
	}
}

//Folder拷贝构造函数
Folder::Folder(const Folder& f) :msg(f.msg)
{
	add_to_Message(f);
}

//从对应的Meesage指针集合中删除本Message
void Folder::remove_from_Message()
{
	for (auto m : msg)
	{
		m->remFolder(this);
	}
}

//析构函数
Folder::~Folder()
{
	remove_from_Message();
}

//拷贝赋值运算符
Folder& Folder::operator=(const Folder& f)
{
	remove_from_Message();
	msg = f.msg;
	add_to_Message(f);
	return *this;
}

练习13.37:

两个成员函数为addFolder和remFolder,两成员函数实现如下所示

//addFolder实现
void Message::addFolder(Folder* f)
{
	folders.insert(f);
}

//remFolder实现
void Message::remFolder(Folder* f)
{
	folders.erase(f);
}

最终两个类的定义为:

#include <iostream>
#include <string>
using namespace std;
#include <vector>
#include <algorithm>
#include <set>

class Folder;
class Message {
	friend class Folder;
	friend void swap(Message& lhs, Message& rhs);
public:
	//folders被隐式初始化为空集合
	explicit Message(const std::string& str = ""):contents(str){ }
	//拷贝构造成员,用来管理指向本Message的指针
	//拷贝构造函数
	Message(const Message&);
	//拷贝赋值运算符
	Message& operator=(const Message&);
	~Message();
	//从给定Folder集合中添加/删除本Message
	void save(Folder&);
	void remove(Folder&);


private:
	//消息内容
	std::string contents;
	//包含message的Folder的set
	std::set<Folder*>folders;
	//拷贝构造函数,拷贝赋值运算符和析构函数所使用的工具函数
	//将Message添加到指向参数的Folder中,Folder指向传递的参数,进行了拷贝,要添加一个Message进去,也就是本Message
	void add_to_Folders(const Message&);
	//从folders中的每一个Folder中删除Message,此Message是此对象的Message
	void remove_from_Folders();

	//与addMsg和remMsg类似的成员函数
	void addFolder(Folder*);
	void remFolder(Folder*);
};

//与Message基本类似,两者是对称的
class Folder {
	friend class Message;
	friend void swap(Message& lhs, Message& rhs);
public:
	//默认构造函数
	Folder(){ };
	//拷贝构造函数
	Folder(const Folder& f);
	//拷贝赋值运算符
	Folder& operator=(const Folder& f);
	//析构函数
	~Folder();
	//Folder版本的save和remove函数
	void save(Message&);
	void remove(Message&);


private:
	std::set<Message*>msg;
	//与Message类似的两个添加删除工具函数
	void add_to_Message(const Folder&);
	void remove_from_Message();
	//向msg中添加或删除一个给定的Message*
	void addMsg(Message* m);
	void remMsg(Message* m);
};

//向msg中添加或删除一个给定的Message*
void Folder::addMsg(Message* m)
{
	msg.insert(m);
}

void Folder::remMsg(Message* m)
{
	msg.erase(m);
}

//save成员函数
void Folder::save(Message& m)
{
	msg.insert(&m);
	//将本Folder添加到m的Folder集合中
	m.addFolder(this);
}

//remove成员函数
void Folder::remove(Message& m)
{
	msg.erase(&m);
	//将本Folder从m的Folder集合中删除
	m.remFolder(this);
}

//将本Folder添加到指向f的Message中
void Folder::add_to_Message(const Folder& f)
{
	for (auto m : f.msg)
	{
		m->addFolder(this);
	}
}

//Folder拷贝构造函数
Folder::Folder(const Folder& f) :msg(f.msg)
{
	add_to_Message(f);
}

//从对应的Meesage指针集合中删除本Message
void Folder::remove_from_Message()
{
	for (auto m : msg)
	{
		m->remFolder(this);
	}
}

//析构函数
Folder::~Folder()
{
	remove_from_Message();
}

//拷贝赋值运算符
Folder& Folder::operator=(const Folder& f)
{
	remove_from_Message();
	msg = f.msg;
	add_to_Message(f);
	return *this;
}


/

void Message::save(Folder& f)
{
	//将给定的Folder添加到我们的Folder列表中
	folders.insert(&f);
	//将本Message添加到f的Message集合中
	f.addMsg(this);
}

void Message::remove(Folder& f)
{
	//将给定Folder从我们的Folder列表中删除
	folders.erase(&f);
	//将本Message从f的Message集合中删除
	f.remMsg(this);
}

//将本Message添加到指向m的Folder中
void Message::add_to_Folders(const Message& m)
{
	//遍历每个包含m的Folder
	for (auto f : m.folders)
	{
		//向每个Folder中添加一个指向本Message的指针
		f->addMsg(this);
	}
}

//Message的拷贝构造函数拷贝给定对象的数据成员
Message::Message(const Message& m) :contents(m.contents), folders(m.folders)
{
	//拷贝构造完成后将本消息添加到指向m的Folder中
	add_to_Folders(m);
}

//从对应的Folder中删除本Message
void Message::remove_from_Folders()
{
	//遍历本Message中的所有Folder,把指向本Message的指针删除
	for (auto f : folders)
	{
		f->remMsg(this);
	}
}

//析构函数
Message::~Message()
{
	remove_from_Folders();
}


//拷贝赋值运算符
Message& Message::operator=(const Message& rhs)
{
	//先从左侧运算对象的folders中删除此Message的指针,然后再将指针添加到右侧运算对象的folders中
	remove_from_Folders();
	contents = rhs.contents;
	folders = rhs.folders;
	//将本Message添加到那些Folder中
	add_to_Folders(rhs);
	return *this;
}

//自定义的swap
void swap(Message& lhs, Message& rhs)
{
	using std::swap;
	//将每个消息的指针从它所在的Folder中删除
	for (auto f : lhs.folders)
	{
		f->remMsg(&lhs);
	}

	for (auto f : rhs.folders)
	{
		f->remMsg(&rhs);
	}

	//交换contents和Folder指针set
	swap(lhs.contents, rhs.contents);
	//交换set&
	swap(lhs.folders, rhs.folders);

	//将每个Message的指针添加到它的(新)Folder中
	for (auto f : lhs.folders)
	{
		f->addMsg(&lhs);
	}


	for (auto f : rhs.folders)
	{
		f->addMsg(&rhs);
	}
}

//addFolder实现
void Message::addFolder(Folder* f)
{
	folders.insert(f);
}

//remFolder实现
void Message::remFolder(Folder* f)
{
	folders.erase(f);
}



int main()
{
	
	system("pause");
	return 0;
}

练习13.38:

这样做也可以达到与我们这里使用的方法一样的效果,但是rhs的一些创建销毁毫无意义,只会使得效率低下,使用我们的方法就可以避免不必要的拷贝操作,性能更高

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白学C++.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值