构造函数:
C++中的类可以定义与类名相同的特殊成员函数
这种与类名相同的成员函数叫做构造函数
构造函数在定义的时候可以有参数,但是没有任何返回类型的声明
class Test
{
private:
int i;
int j;
int k;
public:
Test()
{
i = j = k =0;
}
Test(int v)
{
i = j = k = v;
}
void print()
{
printf("i = %d,j = %d, k = %d\n",i,j,k);
}
void print(int v)
{
printf("v = %d\n",v);
}
};
构造函数的调用:
一般情况下C++编译器会自动调用构造函数
在一些情况下则需要手工调用构造函数
int main(int argc, char** argv) {
Test t1(4); //自动调用构造函数
Test t2 = 5;//自动调用构造函数
Test t3 = Test(8);//手动调用构造函数
//Test tA[3] ; ERROR
Test tA[3] = {Test(1),Test(2),Test(3)}; //手动调用构造函数
for(int i = 0; i< 3;i++)
{
tA[i].print();
}
t1.print();
t2.print();
t3.print();
getchar();
return 0;
}
成员函数的重载:
类的成员函数与普通函数一样可以进行重载,并遵守相同的重载规则。
class Test
{
private:
int i;
int j;
int k;
public:
Test()
{
i = j = k =0;
}
Test(int v)
{
i = j = k = v;
}
void print()
{
printf("i = %d,j = %d, k = %d\n",i,j,k);
}
void print(int v)
{
printf("v = %d\n",v);
}
};
两个特殊的构造函数:
class Test
{
public:
/*
Test()
{
printf("Test()\n");
}
*/
Test(const Test& obj)
{
printf("Tset(const Test& obj)");
}
};
int main(int argc, char** argv) {
Test t1;
Test t2 = t1;
getchar();
return 0;
}
两个特殊的构造函数分别是:
无参构造函数:当类中没有定义任何一种构造函数的时候,编译器默认提供一个无参构造函数,并且它的函数体为空,不做任何处理,只是使得编译通过
拷贝构造函数:当类中没有定义拷贝构造函数的时候,编译器默认提供一个拷贝构造函数,简单的进行成员变量的值复制。
#include <iostream>
#include <stdio.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
/*
注意:
1:当类中没有定义任何一个构造函数,C++编译器会为我们提供无参构造函数和拷贝构造函数
2:当类中定义了任意的非拷贝构造函数时,C++编译器不会为我们提供无参构造函数
3:当类中定义了一个拷贝构造函数时,编译器也不会提供无参构造函数
*/
class Test
{
private:
int i;
int j;
int k;
public:
void print()
{
printf("i = %d, j = %d , k = %d\n", i,j,k);
}
};
int main(int argc, char** argv) {
Test t1;//调用无参构造函数,函数体为空,不做任何事情,就是为了可以编译通过
Test t2 = t1;
//这里输出的值一样,说明系统提供的拷贝构造函数做了一些事情,就是成员变量的复制,这里就是把
//t1的成员变量的值都赋值给t2的成员变量,所以两者输出的一样。
t1.print();
t2.print();
getchar();
return 0;
}
上面代码,最重要的注意是: t1.print()与t2.print()输出的值一样,因为 t2 = t1 这里调用了编译器自己提供的默认拷贝构造函数
它做的事情就是简单的成员变量的赋值,即:t2.i = t1.i;t2.j = t1.j; t2.k = t1.k;所以两者输出的值是一样的。
写一个数组类:
#include <iostream>
#include <stdio.h>
#include "Array.h"
int main(int argc, char** argv) {
Array a1(10);
for(int i = 0 ;i < a1.length(); i++)
{
a1.setData(i,i);
}
for(int i = 0; i< a1.length(); i++)
{
printf("Element i = %d\n", a1.getData(i));
}
printf("**********************************\n");
Array a2 = a1;
for(int i = 0; i< a2.length(); i++)
{
printf("Element i = %d\n", a2.getData(i));
}
a1.destory();
a2.destory();
//如果这里才用系统提供的默认的拷贝构造函数,它只是进行单纯的复制工作,所以a1与a2中的mSpace指向的是
//同一个空间,当执行a1.destory之后,这片空间已经释放,执行a2.destory就会出错
getchar();
return 0;
}
#ifndef _ARRAY_H_
#define _ARRAY_H_
#endif
class Array
{
private:
int mLength;
int *mSpace;
public:
Array(int length);
Array(const Array& obj);
int length();
void setData(int index, int value);
int getData(int index);
void destory();
};
#include "Array.h"
Array::Array(int length)
{
if(length < 0)
length = 0;
mLength = length;
mSpace = new int[mLength];
}
Array::Array(const Array& obj)
{
mLength = obj.mLength;
mSpace = new int[mLength]; //自己申请一个新的空间出来,而系统提供的就是指向同一个空间。
for(int i = 0; i < mLength; i++)
{
mSpace[i] = obj.mSpace[i];
}
}
int Array::length()
{
return mLength;
}
void Array::setData(int index , int value)
{
mSpace[index] = value;
}
int Array::getData(int index)
{
return mSpace[index];
}
void Array::destory()
{
mLength = -1;
delete[] mSpace;
}
总结:
构造函数是C++中用于初始化对象状态的特殊函数
构造函数在对象创建的时候自动被调用
构造函数和普通成员函数都遵循重载规则
拷贝构造函数是对象正确初始化的重要保证
注意:
1:当类中没有定义任何一个构造函数,C++编译器会为我们提供无参构造函数和拷贝构造函数
2:当类中定义了任意的非拷贝构造函数时,C++编译器不会为我们提供无参构造函数,但是会提供默认的拷贝构造函数
class Test
{
public:
Test()
{
printf("Test()\n");
}
/*
Test(const Test& obj)
{
printf("Tset(const Test& obj)");
}
*/
};
int main(int argc, char** argv) {
Test t1;
Test t2 = t1;
getchar();
return 0;
}
上面代码只提供了一个非拷贝构造函数,但是Test t2 = t1 仍然编译通过,说明编译器为我们提供了默认的拷贝构造函数。
3:当类中定义了一个拷贝构造函数时,编译器也不会提供无参构造函数(总之只要有一个我们自己添加的构造函数,编译器就不会再提供无参构造函数)