2013.8.25补充
1、没有进行初始化的实例变量的值是任意的,例如:
class A
{
public:
int a;
};
A a;
count << a.a << endl; // 如果是a定义在全局范围内,则基本数据类型的数据成员初始化为0,如果定义在局部范围内,则值是随机的。
2、赋值运算符“=”,并不是构造函数,有些书上把它叫做赋值构造函数,这是不好的。当我们没有重载赋值运算符的时候,编译器会自动加入一个默认的运算符函数,当类中没有动态分配存储空间的变量和指针变量的时候,这个默认的赋值运算符函数能够满足我们的要求,但是,当类中有动态分配存储空间的变量和指针变量的时候,我们必须重写赋值运算符。
3、当我们的类中没有重载拷贝构造函数的时候,编译器也会给我们加入一个默认的拷贝构造函数,与赋值运算符一样,我们的类中有动态分配存储空间的变量和指针变量的时候,我们必须重写赋值运算符。
4、默认的不带任何参数的构造函数
class A
{
public:
int a;
};
例如上面的A类,当类中没有显示声明任何构造函数的时候(包括赋值构造函数,不包括赋值运算符,因为它根本不是构造哈数),编译器会自动加入一个不带任何参数的构造函数,但它什么也没做,没有对实例变量进行初始化。
当我们的类中显示声明任何一个构造函数的时候(包括赋值构造函数,不包括赋值运算符,因为它根本不是构造哈数),该没有任何参数的默认构造函数就不会被编译器自动加入了。
5、const是可以用来进行函数重载的,例如void a(int a); void a(const int a)是两个不同的函数,函数返回值不作为函数重载的依据。
6、对于类A来说, A(const A &a)和 A(A &a)都是它的拷贝构造函数,当我们在类A中没有声明这两个函数时,编译器会自动加入A(const A &a),因为const有很多好处,可以防止传入的A的对象被修改,还可以接受const和非const变量的参数。当我们在类中声明A(A &a)的时候,编译器就不会加入A(const A &a)这个拷贝构造函数
const A a;
A b(a);
A b = a; // 等价于A b(a); 都会调用 A(const A &a);
就会报错,因为它们寻找的是A(const A &a)这个函数,然而它并不存在,赋值运算符的情况与它相同
7、
A d; 调用A();
const A a; 调用 A();
A b; 调用 A();
b = a; 类A中如果存在 A& operator=(const A&),则调用;如果不存在,则报错
b = d; 类A中如果存在 A& operator=(A &),则调用;如果不存在,则调用A& operator=(const A&),此时A& operator=(const A&)是一定存在的,因为我们没有声明A& operator=(A &),如果我们再没有重写A& operator=(const A&),编译器会自动加入,如果我们重写啦,那它当然存在了。
8、 A(int a)和A(int &a)属于函数重载,因为它们同时存在时是合法的,只要不发生对它们的调用都是正确的,但是
int c;
c=10;
A(c);这时就会发生调用二义性
------------------------------------------------------------------------------------------------------
#include<iostream> using namespace std; class A { public: A(); //如果不定义任何构造函数,系统会自动添加该没有任何参数的构造函数 A(int b); A(int &b); A(const A &b); //如果不定义该构造函数,系统会自动添加 //A(A b); 这样定义发生错误,参数不能只包含A类的变量,因为这样会造成构造函数的无限循环
//A(const A b); 同上
A(A b, int a); int a; }; A::A() { a = 10; } A::A(int b) { a = b; } A::A(int &b) { a = b; } A::A(const A &c) { a = c.a; cout << "copy constructor" << endl; } void show(A a) { cout << a.a << endl; } void show(A &a) { cout << a.a << endl; } int main(void) { A a1; //调用A(); A a2(a1); //调用A(const A &b); //int c=10; //A a(c); 错误:A(int b)和A(int &b)出现二义性 A a3(10); //调用A(int b); 引用是对变量的引用,而10是常量,所以只会调用 A(int b); //对于上面定义的void show(A a)和void show(A &a),如果main函数里面没有发生调用,它不会出现编译错误 //如果出现了调用 show(a1),则发生编译错误,这时void show(A a)和void show(A &a)不能共存, //如果留下void show(A a),则在调用show(a1)的过程中,实参传递给形参的时候,调用A(const A &b); //如果留下void show(A &a),则在调用show(a1)的过程中,实参传递给形参的时候,没有调用A(const A &b); return 0; }