【足迹C++primer】45、拷贝控制示例

拷贝控制示例

那么接下来尽情欣赏这个案例吧!!!

/**
* 功能:拷贝控制示例
* 时间:2014年7月14日10:57:39
* 作者:cutter_point
*/

#include<iostream>
#include<set>
#include<vector>
#include<string>

using namespace std;

class Folder;
/**
Message类
*/
class Message
{
    friend void swap(Message&, Message&);
    friend class Folder;
public:
    //folders被隐式初始化为空集合
    explicit Message(const string &str=""):contents(str){}
    //拷贝控制成员,用来管理指向本Message的指针
    Message(const Message&);        //拷贝构造函数
    Message& operator=(const Message&); //拷贝赋值运算符
    ~Message();                     //析构函数
    //从给定的Folder中添加/删除本Message
    void save(Folder&);
    void remove(Folder&);
    //显示有几个Message对象
    void show();
private:
    string contents;        //实际消息文本
    set<Folder*> folders;   //包含本Message的folder
    //拷贝构造函数,拷贝赋值运算符合析构函数所使用的工具函数
    //将本message添加到指向参数的folder中
    void add_to_Folders(const Message&);
    //从folders中的每个Folder中删除本Message
    void remove_from_Folders();
    //向folders添加和删除
    void addFldr(Folder *f){folders.insert(f);}
    void remFldr(Folder *f){folders.erase(f);}
};

/**
Folder类
*/
class Folder
{
    friend void swap(Message&, Message&);
    friend class Message;
public:
    //构造函数
    Folder()=default;
    //拷贝构造函数
    Folder(const Folder&);
    //拷贝赋值运算符
    Folder & operator=(const Folder&);
    //析构函数
    ~Folder();

    //对应的save和remove函数
    void save(Message&);
    void remove(Message&);

    //显示有几个Message
    void show();

private:
    set<Message*> msgs;         //用来保存当前Folder保存的各种Message对象
    //拷贝构造函数,拷贝赋值运算符合析构函数所使用的工具函数
    //将本message添加到指向参数的folder中
    void add_to_Message(const Folder&);
    //从folders中的每个Folder中删除本Message
    void remove_from_Message();
    void addMsg(Message *m){msgs.insert(m);}       //添加一个对象
    void remMsg(Message *m){msgs.erase(m);}

};

/**
展示有几个set成员
*/
void Message::show()
{
    cout<<"folders的个数有:"<<folders.size()<<endl;
}

void Folder::show()
{
    cout<<"msgs的个数有:"<<msgs.size()<<endl;
}

/**
save和remove成员
*/
void Folder::save(Message &m)
{
    msgs.insert(&m);
    m.addFldr(this);
}

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

void Folder::remove(Message &m)
{
    msgs.erase(&m);
    m.remFldr(this);
}

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

/**
Message类的拷贝控制成员
*/
//将本Message添加到指向m的Folder中
void Message::add_to_Folders(const Message &m)
{
    for(auto f : m.folders)     //对每个包含m的set的folder
        f->addMsg(this);        //向Folder添加一个指向本Message的指针
}

Message::Message(const Message &m):contents(m.contents), folders(m.folders)
{
    add_to_Folders(m);
}

/**
Message的析构函数
*/
//对应的Folder中删除本Message,这个是析构函数要用到的工具函数
void Message::remove_from_Folders()
{
    for(auto f : folders)
        f->remMsg(this);        //从该Folder中删除本Message
}

Message::~Message()
{
    remove_from_Folders();
}

/**
Message的拷贝赋值运算符
*/
Message& Message::operator=(const Message &rhs)
{
    //先把本对象的全部指针清空,准备接受右边的赋值
    remove_from_Folders();      //更新已有的Folder
    contents=rhs.contents;
    folders=rhs.folders;
    //将本文本添加发哦相应的Folders中
    add_to_Folders(rhs);

    return *this;
}

/**
Message的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);

    //交换相应的数据
    swap(lhs.folders, rhs.folders); //swap(set&, set&)
    swap(lhs.contents, rhs.contents);   //swap(string&, string&)

    //将每个Message的指针添加到它的(新)Folder中,已经交换了
    for(auto f : lhs.folders)
        f->addMsg(&lhs);
    for(auto f : rhs.folders)
        f->addMsg(&rhs);
}

/**
Folder的拷贝构造,拷贝赋值运算符,析构函数定义
*/
void Folder::add_to_Message(const Folder &f)
{
    for(auto m : f.msgs)
        m->addFldr(this);
}

Folder::Folder(const Folder &f):msgs(f.msgs)
{
    add_to_Message(f);
}

//拷贝赋值运算符void remove_from_Message
void Folder::remove_from_Message()
{
    for(auto m : msgs)       //清除全部指针
        m->remFldr(this);
}

Folder& Folder::operator=(const Folder &rhs)
{
    //先把本对象的所有指针清空
    remove_from_Message();
    msgs=rhs.msgs;

    //赋值完成后添加到那些message中
    add_to_Message(rhs);

    return *this;
}

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

int main()
{
    string s1("cutter_point1");
	string s2("cutter_point2");
	string s3("cutter_point3");
	string s4("cutter_point4");
	string s5("cutter_point5");
	string s6("cutter_point6");

	// all new messages, no copies yet
	Message m1(s1);
	Message m2(s2);
	Message m3(s3);
	Message m4(s4);
	Message m5(s5);
	Message m6(s6);

	Folder f1;
	Folder f2;

	m1.save(f1); m3.save(f1); m5.save(f1);
	m1.save(f2);
	m2.save(f2); m4.save(f2); m6.save(f2);

	// create some copies
	Message c1(m1);
	Message c2(m2), c4(m4), c6(m6);

	// now some assignments
	m2 = m3;
	m4 = m5;
	m6 = m3;
	m1 = m5;

	// finally, self-assignment
	m2 = m2;
	m1 = m1;

	vector<Message> vm;
	cout << "capacity(初始vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m1);

	cout << "capacity(添加m1后vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m2);

	cout << "capacity(添加m2后vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m3);

	cout << "capacity(添加m3后vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m4);

	cout << "capacity(添加m4后vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m5);

	cout << "capacity(添加m5后vm容纳量): " << vm.capacity() << endl;
	vm.push_back(m6);
	cout << "capacity(添加m6后vm容纳量): " << vm.capacity() << endl;

	vector<Folder> vf;
	cout << "capacity(初始vf容纳量): " << vf.capacity() << endl;
	vf.push_back(f1);

	cout << "capacity(添加f1后vf容纳量): " << vf.capacity() << endl;
	vf.push_back(f2);

	cout << "capacity(添加f2后vf容纳量): " << vf.capacity() << endl;
	vf.push_back(Folder(f1));

	cout << "capacity(再添加f1后vf容纳量): " << vf.capacity() << endl;
	vf.push_back(Folder(f2));

	cout << "capacity(再添加f2后vf容纳量): " << vf.capacity() << endl;
	vf.push_back(Folder());
	cout << "capacity(再添加空Folder后vf容纳量): " << vf.capacity() << endl;

	Folder f3;
	f3.save(m6);
	vf.push_back(f3);
	cout << "capacity(再添加空f3后vf容纳量): " << vf.capacity() << endl;

	cout<<"m1到m6中folders的个数:"<<endl;
	m1.show(); m2.show(); m3.show();
	m4.show(); m5.show(); m6.show();
	cout<<"f1到f3中Message的个数:"<<endl;
	f1.show(); f2.show(); f3.show();
	cout<<"c1,c2,c4,c6中folders的个数:"<<endl;
	c1.show(); c2.show();
	c4.show(); c6.show();

    return 0;
}

这个我运行出了结果,给大家看一看!!

【足迹C++primer】45、拷贝控制示例

时间: 2024-10-25 02:48:34

【足迹C++primer】45、拷贝控制示例的相关文章

【C++ Primer 第十三章】4. 拷贝控制示例

拷贝控制示例 1 #include<iostream> 2 #include<string> 3 #include<set> 4 using namespace std; 5 6 class Folder; 7 8 class Message { 9 friend void swap(Message&, Message&); 10 friend class Folder; 11 public: 12 explicit Message(const stri

拷贝控制示例

实现二个类,一个是Message,另一个是Folder:类似于消息和消息目录,每个Message对象可以出现在多个Folder中.但是,任意给定的Message的内容只有一个副本.其结构依赖:为了记录Message位于哪些Folder中,每个Message都会保存一个它所在Folder的指针的set,同样的,每个Folder都保存一个它保存一个它包含的Message的指针的set. 首先是Message的头文件: 1#ifndef _MESSAGE_ 2 #define _MESSAGE_ 3

C++ Primer 笔记——拷贝控制

1.如果构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是引用类型(否则会无限循环的调用拷贝构造函数). 2.如果没有为一个类定义拷贝构造函数,编译器会为我们定义一个合成拷贝构造函数.与合成默认构造函数不同,即使我们定义了其他的构造函数,编译器也会为我们合成一个拷贝构造函数. 3.合成的拷贝构造函数会将其参数的成员逐个拷贝到正在创建的对象中(除了static成员).对于类类型的成员,会使用其拷贝构造函数来拷贝,虽然我们不能

【C++ Primer】拷贝控制

十三.复制控制 1. 复制构造函数 类中的成员函数都默觉得inline类型.所以即使在类定义体内的函数声明显示定义为inline类型,在进行函数定义时也可以将inline进行省略. // 复制构造函数应该为常量引用类型,假设同意传值參数会造成无限循环调用从而导致内存溢出. CopyConstruct(const CopyConstruct& a){value = a.value;} 复制构造函数可用于初始化顺序容器中的元素,如vector<string> svec(5); 这样的方式使

C++11(12):拷贝控制

拷贝构造函数的第一个参数必须是引用类型,此参数几乎总是const的引用.拷贝构造函数在几种情况下会隐式地使用.因此,拷贝构造函数不应该是explicit的 即使我们定义了其他构造函数,在没有拷贝构造函数时,编辑器也会为我们合成的.编辑器从给定对象中依次将每个非static成员拷贝到创建的对象中.每个成员决定了它使用何种方式进行拷贝.类调用拷贝构造函数,数组逐个拷贝,内置类型直接拷贝 string dots(10,'.')  //直接初始化 string noll_book="999999&quo

【足迹C++primer】54、继承类的范围,构造函数和拷贝控制

继承类的范围,构造函数和拷贝控制 当用派生类执行函数的时候,首先会在当前的类里面找 如果找不到就一级一级地往上找. Name Lookup Happens at Compile Time class Quote { public: Quote()=default; Quote(const string &book, double sales_price):bookNo(book), price(sales_price) {cout<<"Quote gouzhao functi

【足迹C++primer】43、拷贝控制和资源管理

拷贝控制和资源管理 13.2.1行为像值的类 *定义一个拷贝构造函数,完成string的拷贝,而不是拷贝指针 *定义一个析构函数来释放string *定义一个拷贝赋值运算符来释放对象当前的string,并从右侧运算对象拷贝string class HasPtr { public: HasPtr(const string &s=string()):ps(new string(s)), i(0){} //对ps指向的string,每个HasPtr对象都有自己的拷贝 HasPtr(const HasP

【足迹C++primer】42、拷贝、赋值与销毁(1)

拷贝.赋值与销毁(1) 13.1.1拷贝构造函数 /************************************** 13.1.1拷贝构造函数 **************************************/ class Foo1 { public: Foo1(); //默认构造函数 Foo1(const Foo1&); //拷贝构造函数 //... }; 注意:拷贝构造函数的第一个参数必须是一个参数 合成拷贝构造函数 /************************

【C++ Primer 第13章】2. 拷贝控制和资源管理

拷贝控制和资源管理 • 类的行为像一个值.意味着它应该有自己的状态,当我们拷贝一个像值得对象时,副本和原对象是完全独立的,改变副本不会对原对象有任何影响. • 行为像指针的类则共享状态.当我们拷贝一个这种类的对象时,副本和原对象使用相同的底层数据,改变副本也会改变原对象. 13.2节练习 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 class HasPtr { 6 public: 7 HasP