县城购物网站,免费网站生成软件,wordpress与typecho,网站建设合同书保密条款欢迎转载#xff0c;但请标明作者 “九天雁翎”#xff0c;当然#xff0c;你给出这个帖子的链接更好。 还记得#xff08;1#xff09;中讲到的构造函数吗#xff1f;复习一下#xff0c;这次我们重载一个新的默认构造函数--即当你不给出初始值时调用的构造函数#x… 欢迎转载但请标明作者 “九天雁翎”当然你给出这个帖子的链接更好。 还记得1中讲到的构造函数吗复习一下这次我们重载一个新的默认构造函数--即当你不给出初始值时调用的构造函数我记得我讲过这个概念吧有吗看下面的例子。 例6.0 #include string #include iostream using namespace std; class Fruit //定义一个类名字叫Fruit { string name; //定义一个name成员 string colour; //定义一个colour成员 public: void print() //定义一个输出名字的成员print() { coutcolour nameendl; } Fruit(const string nst,const string cst green):name(nst),colour(cst) //构造函数 { name s; } Fruit(istream is cin) //新的构造函数 { iscolourname; } }; int main() { Fruit apple(apple); //定义一个Fruit类对象apple Fruit apple2; apple.print(); apple2.print(); return 0; } 发现我重载的默认构造函数没有这次利用的是默认形参(istream is cin)学过io的就应该知道他的意思表示默认就是从标准设备输入如键盘。你运行下就知道怎么回事了。现在我们讲一个新内容复制构造函数什么意思先看下面的例子。 例6.1 #include string #include iostream using namespace std; class Fruit //定义一个类名字叫Fruit { string name; //定义一个name成员 string colour; //定义一个colour成员 public: void print() //定义一个输出名字的成员print() { coutcolour nameendl; } Fruit(const string nst,const string cst green):name(nst),colour(cst) //构造函数 { name s; } Fruit(){} }; int main() { Fruit apple(apple); //定义一个Fruit类对象apple Fruit apple2(apple);//发现这里有什么问题没有 apple.print(); apple2.print(); return 0; } 你会发现apple2也输出了green apples为什么啊apple)和(apple)一样你这这样理解可就错了肯定不一样嘛。但是当我们使用Fruit apple2(apple);的时候调用了哪个构造函数呢我们没有定义一个类似的构造函数啊按道理应该编译失败不是吗恩这里调用的构造函数就叫做复制构造函数即用一个同样类型的对象构造另一个对象的构造函数,不过在这里我们没有定义所以由系统帮我们自动定义的叫做默认复制构造函数。效果自然就是复制一下。你把第一个对象改成apple3你就会发现apple2没有办法定义了因为它调用的是复制Fruit对象apple的构造函数而不是用字符串apple那个构造函数。C Primer这样定义复制构造函数我引用一下“只有单个形参而且该形参是对本类类型对象的引用常用const修饰”。我们来看看系统合成的默认复制构造函数的一个有趣应用 例6.2 #include iostream using namespace std; class Aint { public: int aival[3]; }; int main() { Aint as{1,2,3}; coutas.aival[0]as.aival[1]as.aival[2]endl; Aint bs(as); coutbs.aival[0]bs.aival[1]bs.aival[2]endl; return 0; } 很简单的例子吧不过也很有趣我们都知道数组是没有办法通过等于来复制的要复制只能利用循环遍历我们自己定义了一个只包含整形数组的类而当我们利用系统合成的默认复制构造函数的时候实现了数组的复制注意是一次性等于复制。呵呵。这也说明了一个问题就是系统的默认复制构造函数在对付数组时帮我们遍历复制了。现在我们自己定义一个复制构造函数。要说明的是一般情况下系统定义的复制构造函数已经够用了当你自己要定义的时候是想实现不同的功能比如更好的处理指针的复制等下面的例子只是看看用法我也只讲用法而不讲究有没有实际意义。 例6.3 #include string #include iostream using namespace std; class Fruit //定义一个类名字叫Fruit { string name; //定义一个name成员 string colour; //定义一个colour成员 public: void print() //定义一个输出名字的成员print() { coutcolour nameendl; } Fruit(const string nst apple,const string cst green):name(nst),colour(cst){} //构造函数 Fruit(Fruit aF):name(aF.name),colour(aF.colour) //这是我们自己定义的复制构造函数 { name s; //让他和默认的不同 } }; int main() { Fruit apple; //定义一个Fruit类对象apple Fruit apple2(apple);//调用的是我们自己定义的复制构造函数 apple.print(); apple2.print(); //你会发现输出多了个s return 0; } 这里你会看到我们自己定义的复制构造函数的作用直观的看到apple只输出green apple,而apple2输出green aples要说明的是这也是复制构造函数也是构造函数也可以用初始化列表而且在C Primer中还推荐你使用初始化列表。下面我们看看假如你向让你的类禁止复制怎么办啊很简单让你的复制构造函数跑到private里面去这时候友元和成员还可以使用复制那你就光声明一个复制构造函数但是你不定义它在C里面光声明不定义一个成员函数是合法的但是使用的话就会导致编译失败了普通函数也是这样通过这种手段你就能禁止一切复制的发生了其实是发现一切本需要复制构造函数的地方了。见下例。 例6.4 #include string #include iostream using namespace std; class Fruit //定义一个类名字叫Fruit { string name; //定义一个name成员 string colour; //定义一个colour成员 public: void print() //定义一个输出名字的成员print() { coutcolour nameendl; } Fruit(const string nst apple,const string cst green):name(nst),colour(cst) {} //构造函数 private: Fruit(Fruit aF); //把它定义在private下 }; int main() { Fruit apple(apple); //定义一个Fruit类对象apple // Fruit apple2(apple); //你这样的尝试会导致编译失败的cannot access private 错误 apple.print(); return 0; } 在犯了一个我半天也没有发现的错误的后我发现了当利用形如Fruit apple2 apple方式来定义并初始化一个对象的时候调用的也是复制构造函数详情请见那个帖子《警惕C里面“”不一定就是等于赋值。 》