若C++没有定义构造函数则,编译器会自动创建默认的构造函数。若定义了构造数则C++不会定义默认的构造函数,若创建对象时需要显式的对其进行初始化或者是创建对象数组时,则必须显式地定义默认构造函数。
StringBad ()
{
hours=0;
minutes=0;
}
通常为了方便起见,将定义的构造函数与默认的构造函数综合在一起,这里都是在类声明中直接定义的
StringBad(int h=0,int m=0)
{
hours=h;
minutes=m;
}
复制构造函数就是将一个对象复制到新创建的对象中去,它用于初始化过程中,而不是常规的赋值过程中,类的复制构造
函数的原型通常如下:
class_name(const class_name &);
新建一个对象并将其初始化同类现有对象时,复制构造函数将被调用。
StringBad ditto(motto);
StringBad metoo=motto;
StringBad also=StringBad("good")//此时编辑器会通过构造函数创建一个临时的对象,然后将该对象复制给also,此时会再调用复制构造函数的。
StringBad*pStringBad=new StringBad(motto);//使用motto初始化一个匿名对象,并将新对象的地址赋给pstring指针。每当程序生成了对象的副本时,编译器都将使用复制构造函数。
静态成员函数
可以将成员函数声明为静态的,函数声明中前必须包含关键字static。
首先它不能通过对象调用静态成员函数,甚至不能使用this指针。如果静态成员函数是在公有部分声明的,则可以使用类名和作用域解析符调用它。其次,由于静态成员函数不与特定的对象相关联,因此只能使用静态数据成员。
程序一:默认的构造函数和自定义的复制构造函数的应用
#include<iostream>
using namespace std;
class StringBad
{
private:
int hours;
int minutes;
public:
StringBad (int h=0,int m=0)
{
hours=h;
minutes=m;
cout<<"called the constructor"<<endl;
cout<<hours<<":"<<minutes<<endl;
}
StringBad(const StringBad &)
{
cout<<"called the copy_constructor"<<endl;
}
};
int main()
{
StringBad time1(8,10);
StringBad time2=time1;//语句1
StringBad time3=StringBad(9,30);//语句3
return 0;
}
在语句1:首先创建一个自定义的默认的构造函数,语句2通过一个复制构造函数将对象time1复制给time2.
语句3先通过定义的构造函数将创建一个临时的对象存储(9,30),然后通过复制构造函数将临时对象复制给time3.
程序二:静态成员函数的应用
#include<iostream>
using namespace std;
class StringBad
{
private:
int hours;
int minutes;
static int num_time;
public:
StringBad (int h=0,int m=0)
{
hours=h;
minutes=m;
num_time++;
cout<<"called the constructor"<<endl;
cout<<hours<<":"<<minutes<<endl;
}
StringBad(const StringBad &)
{
cout<<"called the copy_constructor"<<endl;
}
static void show()
{
cout<<"num_time="<<num_time<<endl;
}
};
int StringBad::num_time=0;
int main()
{
StringBad time1(8,10);
StringBad time2(9,20);
StringBad time3(11,20);
StringBad time4(7,20);
StringBad::show();
return 0;
}
在类声明中,我们定义num_time为创建对象的次数,当没创建一个对象时,则num_time增加一次。对于访问静态成员函数,只有通过类名和作用域符号::两者共同访问。其中静态函数成员只能对静态变量进行操作,这也反过来证明不能通过对象或者this指针来访问静态成员函数。