[Effective C++ --012]复制对象时勿忘其每一个成分
引言:
在深拷贝和浅拷贝的理解中,我们知道了“拷贝构造函数”一词,并且也了解了它的构成。
A(const A& r); // 形式有多种,在这里只列出一个
因此,在值传递的应用场景里,我们可以写出以下的拷贝构造函数:
#include <iostream>
#include<string>
using namespace std; class A {
public:
A(int i) : count(i) {};
A(const A& r) { // 拷贝构造函数
count = r.count;
}
~A() {};
void out() {
cout << "count:" << count << endl;
}
private:
int count;
}; int main()
{
A a();
A a1(a); // 将a的临时变量传递进去 a1.out();
return ;
}
输出结果:1
一、不要忘记复制每一个成员
在引言的例子里,我们完整将count通过拷贝构造函数复制了过来。如果我们此时有了新需求,需要给类A增加一个成员x,那么在拷贝构造函数中,一定不要忘记拷贝x!
#include <iostream>
using namespace std; class A {
public:
A(int i, int j) : count(i),x(j) {};
A(const A& r) {
count = r.count;
x = r.x; // 不要忘记赋值成员x!
}
~A() {};
void out() {
cout << "count:" << count << endl;
cout << "x:" << x << endl;
}
private:
int count;
int x;
}; int main()
{
A a(, );
A a1(a); a1.out();
return ;
}
值得注意的是:如果我们遗漏了第9行代码,编译器是不会报错的,甚至也能正常运行,但是不会得出想要的结果1!
二、拥有"显示"拷贝构造函数发生继承
在上面的A类中, 我们已经针对A写出了显示的拷贝构造函数。但是如果此时发生了继承会怎么样呢?
假设我们有class B: public A
class B: public A {
public:
B(int x, int y) : b1(x),b2(y){};
B(const B& r){
b1 = r.b1;
b2 = r.b2;
};
~B() {};
void out() {
cout << "b1:" << b1 << endl;
cout << "b2:" << b2 << endl;
}
private:
int b1, b2;
};
简直跟class A一样有木有?
于是我们开始编译 B b(2,2); B b1(b);
会出现以下错误:
error C2512: 'CPS' : no appropriate default constructor available
这是为什么呢?
在类B的拷贝函数中看起来好像赋值了B中的每一个东西,但是它们复制的只是B声明的成员变量b1,b2;B继承A的成员变量附件完全木有得到复制啊!
在创建对象时,会首先调用A类的构造函数。而在B的初始化列表中,并没有显示的对基类的构造函数进行调用。那么,系统会默认调用A的无参构造函数,但是你的A类并没有定义无参构造函数,所以出错了!
改法如下:
class B: public A {
public:
B(int x, int y) : b1(x),b2(y), A(x, y) {}; // 调用A的构造函数
B(const B& r) : A(r.b1, r.b2){ // 调用A的构造函数
b1 = r.b1;
b2 = r.b2;
};
~B() {};
void out() {
cout << "b1:" << b1 << endl;
cout << "b2:" << b2 << endl;
}
private:
int b1, b2;
};
◆总结
1.拷贝函数应该确保复制对象内的所有成员变量及所有的基类成分。
2.不要尝试以某个拷贝函数实现另一个拷贝函数。应该将共同机能放进第三个函数中,并由两个拷贝函数共同调用。
[Effective C++ --012]复制对象时勿忘其每一个成分的更多相关文章
- EC笔记:第二部分:12、复制对象时勿忘其每一个成分
EC笔记:第二部分:12.复制对象时勿忘其每一个成分 1.场景 某些时候,我们不想使用编译器提供的默认拷贝函数(包括拷贝构造函数和赋值运算符),考虑以下类定义: 代码1: class Point{ p ...
- Effective C++_笔记_条款12_复制对象时勿忘其每一个成分
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 编译器会在必要时候为我们的classes创建copying函数, ...
- Effective C++ -----条款12: 复制对象时勿忘其每一个成分
Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...
- Effective C++ 条款12:复制对象时勿忘其每一个成分
void logCall(const std::string& funcName); class Customer { public: ... Customer (const Customer ...
- EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分
记住: ★copying函数应确保复制“对象内的所有成员变量”及“所有base class成分” ★不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两 ...
- 条款12:复制对象时勿忘其每一个成分(Copy all parts of an object)
NOTE: 1.Copying 函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 2.不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个 ...
- C++复制对象时勿忘每一部分
现看这样一个程序: void logCall(const string& funcname) //标记记录 { cout <<funcname <<endl; } cl ...
- Effective C++(12) 复制对象时要复制每一个成员
问题聚焦: 负责拷贝的两个操作:拷贝构造函数和重载赋值操作符. 一句话总结,确保被拷贝对象的所有成员变量都做一份拷贝. Demo void logCall(const std::string&am ...
- Effective C++:规定12:不要忘了复制的对象时,它的每一个组成部分
(一个) 继承制度的声明: class Date {...}; class Customer { public: ... private: string name; Date lastTransact ...
随机推荐
- LeetCode Excel Sheet Column Title (输出excel表的列名称)
题意:给一个数字n,输出excel表的列名称. 思路:其实观察可知道,是个26进制的标记而已.那就模拟一下,每次计算一位时就先左移1位,再进行计算. class Solution { public: ...
- POJ 3683 Priest John's Busiest Day (2-SAT,常规)
题意: 一些人要在同一天进行婚礼,但是牧师只有1个,每一对夫妻都有一个时间范围[s , e]可供牧师选择,且起码要m分钟才主持完毕,但是要么就在 s 就开始,要么就主持到刚好 e 结束.因为人数太多了 ...
- 【转】禁止seekbar的拖动事件
原文网址:http://blog.csdn.net/ansionnal/article/details/8229801 当然是可以的! 其实是 onTouchEvent 事件时,不让他传递事件就行了! ...
- HTML.ActionLink 和Html.Action和 Url.Action 的区别
1. html.ActionLink生成一个<a href=".."></a>标记..例如:@Html.ActionLink(“链接文本”.“someact ...
- Jenkin+TestNG进行自动化测试执行
1.登陆jenkins'后,主页面有一个jenkins管理选项,进入该模块,对插件,系统进行配置.(安装一个extend choice parameter插件) 2.点击new item新建一个项目, ...
- 文件I/O操作(1)
linux系统调用和用户编程接口(api) 系统调用是指在操作系统提供给用户程序调用的一组“特殊”的接口,用户程序可以通过这组特殊的接口来获取操作系统内核提供的服务,例如用户可以通过进程控制相关的系统 ...
- Base-Android快速开发框架(四)--网络操作之FastJson以及AsyncHttpClient
Android的展示数据,除了上章所讲的本地存储外,大部分数据都来自于网络.首先介绍一下Android APP开发常见的网络操作方式.从网络层面上有底层的tcp/ip,也就是我们常见的socket套接 ...
- 寒假训练第九场 Brocard Point of a Triangle
题意:求布洛卡点坐标 思路:直接利用布洛卡点的性质.http://pan.baidu.com/s/1eQiP76E #include<cstdio> #include<cstring ...
- 二叉搜索树算法详解与Java实现
二叉查找树可以递归地定义如下,二叉查找树或者是空二叉树,或者是满足下列性质的二叉树: (1)若它的左子树不为空,则其左子树上任意结点的关键字的值都小于根结点关键字的值. (2)若它的右子树不为空,则其 ...
- adb不响应
1.CMD命令窗口输入:adb nodaemon server .然后就会提示你哪个端口被占用了. 2.输入netstat -ano | findstr "5037" .然后会弹出 ...