定义一个空类时,C++到底默默编写了哪些函数?
2014-05-22 19:50
274 查看
今天看了一本很经典的书籍《Effective C++》中的条款5,感觉书中说得有点混乱,故在此整理一下,并和大家分享一下自己的学习。好,现在开始吧。这个条款可以总结为三个问题:
问题1:当我们定义一个空类的时候,C++编译器会为我们编写哪些函数呢?
问题2:这些默认函数都做了什么工作呢?
问题3:如果要对一个含有“reference成员”的类进行赋值操作,可以依赖编译器生成的赋值重构函数(operator=)吗?
问题1:当我们定义一个空类的时候,C++到底会默默为我们编写哪些函数呢?
例如写了这么一个空类:
class Empty{ };
则,C++会为我们默默地编写了4个函数:一个default构造函数、一个析构函数、一个copy构造函数、一个等号“=”重构函数:
class Empty{
public:
Empty() {......} //default构造函数
Empty(constEmpty& rhs) {.....} //copy构造函数
~Empty() {....} //析构函数
Empty& operator=(constEmpty& rhs) {.....} //等号“=”重构函数(copy
assignment 操作符)
};
当然,这些函数只有在被需要的时候,他们才会被编译器创建出来。
Empty e1; //default构造函数
//析构函数
Empty e2(e1); //copy构造函数
e2=e1; //等号“=”重构函数
如果,在定义类时,把上面四个函数中的一个或者全部都人工声明了,则编译器不再创建对应的函数。
问题2:这些4个函数都为我们只做了些什么呢?
由编译器创建出来的default构造函数和析构函数,其实只是一个空函数,什么也不做;
至于copy构造函数和等号“=”重构函数,他们只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象;
对于static成员变量不用拷贝,因为同属于一个类的不同对象的static成员变量都是一样的。
问题3:如果要对一个含有“reference成员”的类进行赋值操作,可以依赖编译器生成的赋值重构函数吗?
如果要对一个含有“reference成员”的类进行赋值操作,是不可以依赖编译器生成的赋值重构函数的,
必须自己定义一个赋值重构函数。
原因,请看下面的代码:
class NameObject{
public:
NameObjec(std::string&name,const int & value)
{
nameValue=name;
objectValue=value;
}//假设并没有声明 等号“=”重构函数
private:
std::string& nameValue;//引用
const int objectValue;
}:
现在考虑下面会发生什么事?
std::string newDog(Tom);
std::string oldDog(Jack);
NameObject p(newDog,2);//定义一个对象
NameObject s(oldDog,4);//再定义一个对象
p=s;//错误 将s对象赋值给p对象
赋值前,p.nameValue和s.nameValue分别是对象newDog和oldDog的引用,
那么赋值后,p.nameValue应该是指向s.nameValue所指的那个string对象oldDog吗?当然不是。因为在C++中规定,一个引用与某个变量建立联系后,就不能够再作为其他变量的别名了。所以指定p.nameValue为newDog的引用后,p.nameValue不能够再次指定为oldDog的引用了。
int a1,a2;
int &b=a1;//b为a1的别名
int &b=a2;//错误,因为b已经是变量a1的别名了
问题1:当我们定义一个空类的时候,C++编译器会为我们编写哪些函数呢?
问题2:这些默认函数都做了什么工作呢?
问题3:如果要对一个含有“reference成员”的类进行赋值操作,可以依赖编译器生成的赋值重构函数(operator=)吗?
问题1:当我们定义一个空类的时候,C++到底会默默为我们编写哪些函数呢?
例如写了这么一个空类:
class Empty{ };
则,C++会为我们默默地编写了4个函数:一个default构造函数、一个析构函数、一个copy构造函数、一个等号“=”重构函数:
class Empty{
public:
Empty() {......} //default构造函数
Empty(constEmpty& rhs) {.....} //copy构造函数
~Empty() {....} //析构函数
Empty& operator=(constEmpty& rhs) {.....} //等号“=”重构函数(copy
assignment 操作符)
};
当然,这些函数只有在被需要的时候,他们才会被编译器创建出来。
Empty e1; //default构造函数
//析构函数
Empty e2(e1); //copy构造函数
e2=e1; //等号“=”重构函数
如果,在定义类时,把上面四个函数中的一个或者全部都人工声明了,则编译器不再创建对应的函数。
问题2:这些4个函数都为我们只做了些什么呢?
由编译器创建出来的default构造函数和析构函数,其实只是一个空函数,什么也不做;
至于copy构造函数和等号“=”重构函数,他们只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象;
对于static成员变量不用拷贝,因为同属于一个类的不同对象的static成员变量都是一样的。
问题3:如果要对一个含有“reference成员”的类进行赋值操作,可以依赖编译器生成的赋值重构函数吗?
如果要对一个含有“reference成员”的类进行赋值操作,是不可以依赖编译器生成的赋值重构函数的,
必须自己定义一个赋值重构函数。
原因,请看下面的代码:
class NameObject{
public:
NameObjec(std::string&name,const int & value)
{
nameValue=name;
objectValue=value;
}//假设并没有声明 等号“=”重构函数
private:
std::string& nameValue;//引用
const int objectValue;
}:
现在考虑下面会发生什么事?
std::string newDog(Tom);
std::string oldDog(Jack);
NameObject p(newDog,2);//定义一个对象
NameObject s(oldDog,4);//再定义一个对象
p=s;//错误 将s对象赋值给p对象
赋值前,p.nameValue和s.nameValue分别是对象newDog和oldDog的引用,
那么赋值后,p.nameValue应该是指向s.nameValue所指的那个string对象oldDog吗?当然不是。因为在C++中规定,一个引用与某个变量建立联系后,就不能够再作为其他变量的别名了。所以指定p.nameValue为newDog的引用后,p.nameValue不能够再次指定为oldDog的引用了。
int a1,a2;
int &b=a1;//b为a1的别名
int &b=a2;//错误,因为b已经是变量a1的别名了
相关文章推荐
- C++为我们默默编写了哪些函数
- Effective C++ 05 了解C++默默编写并调用哪些函数 笔记
- tip5:了解C++默默编写并调用了哪些函数
- 读书笔记_Effective_C++_条款五:了解C++默默编写并调用哪些函数
- 条款五 了解C++默默的编写并调用的哪些函数
- 条款05:了解C++默默编写并调用哪些函数
- effective C++ 读后感(五) 了解C++默默编写并调用哪些函数
- 条款5:了解C++默默编写并调用哪些函数
- 条款05:了解C++默默编写并调用哪些函数
- 条款05:了解C++默默编写并调用哪些函数(Know what functions C++ silently writes and calls)
- 关于C++——理解C++默默编写并调用了哪些函数&&函数初始化式(初始化列表相关)
- 《Effective C++》学习笔记条款05了解C++默默编写并调用哪些函数
- 【Effective C++】条款5:了解C++默默编写并调用哪些函数
- Effective C++ 条款5——了解C++默默编写并调用哪些函数
- 条款5:了解C++默默编写并调用哪些函数
- C++默默编写并调用哪些函数
- Effective c++学习笔记——条款5:了解C++默默编写并调用哪些函数
- 条款05:了解C++默默编写并调用哪些函数
- Effective C++读书笔记之五:了解C++默默编写并调用哪些函数
- Effective C++ Item 5 了解 C++ 默默编写并调用哪些函数