一. 函数的原型以及函数建立的时机编程
C++中建立一个空类:函数
C++代码学习
class Empty {}; spa
默认会生成4个函数,其函数的原型以下:视频
C++代码对象
public: blog
Empty() { ... } 教程
Empty(const Empty& rhs) { ... } get
~Empty() { ... } 原型
Empty& operator=(const Empty& rhs) { ... }
说明:1) 这些函数只有在须要调用的时候,编译器才会生成。2) 4个函数都是public的。
3) 4个函数都是inline的(即函数定义在类的定义中的函数)。4) 若是你显式的声明了这些函数中的任何一个函数,那么编译器将再也不生成默认的函数。
好比,当遇到下列语句时,函数会被编译器生成:
C++代码
Empty e1; //默认构造函数
//对象销毁时,析构函数
Empty e2(e1);//拷贝构造函数
e2 = e1;//赋值运算符
另外,还存在两种默认的函数:就是取地址运算符和取地址运算符的const版本,这两个函数在《Effective C++》中没有说起。
C++代码
public:
Empty* operator&() { ... }
const Empty* operator&() const { ... }
这两个函数是确实存在的,正以下面的代码能够正常工做:
C++代码
#include <stdio.h>
class Empty {
};
int main(int argc, char** argv)
{
Empty a;
const Empty *b = &a;
printf("%p\n", &a); //调用取地址运算符
printf("%p\n", b); //调用const取地址运算符
}
一个容易被忽略的问题:自定义的拷贝构造函数不只会覆盖默认的拷贝构造函数,也会覆盖默认的构造函数。下面的代码是编译不过的,用户必须再显式的定义一个无参的构造函数。
C++代码
class Empty
{
public:
Empty(const Empty& e) { } //拷贝构造函数
};
int main(int argc, char** argv)
{
Empty a;
}
二. 赋值操做符存在的问题
赋值操做符函数的行为与拷贝构造函数的行为基本是相同的,编译器生成赋值操做符函数是有条件的,若是会产生没法完成的操做,编译器将拒绝产生这一函数。
那么何时编译器没法完成赋值这一行为呢?考虑以下情形(来源Effective C++):
C++代码
template<class T>
class NameObject {
public:
NameObject(std::string& name,const T& value);
private:
std::string& nameValue;//引用成员变量
const T objectValue; //const成员变量
};
而后考虑下面的语句会发生什么事:
C++代码
std::string newDog("abc");
std::string oldDog("xxx");
NameObject
NameObject
p = s;//将会发生什么?
赋值语句以前,p.nameValue指向newDog, s.nameValue指向oldDog。那么赋值以后呢?p.nameValue应该指向s.nameValue指向的对象吗?可是C++有一条规定:引用不能改指向另一个对象。
对于变量objectValue,C++规定:更改const成员是不合法的。
所以若是上面两种情形中的任何一种发生了,C++编译器给出的响应是:拒绝编译这一行的赋值动做。若是你这么作了,C++编译器会报错。
若是你执意要进行赋值操做,那么能够本身定义一个赋值操做符重载函数。
另外若是你想更好的提高你的编程能力,学好C语言C++编程!弯道超车,快人一步!笔者这里或许能够帮到你~
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比本身琢磨更快哦!
编程学习资料: