类的构造函数
构造函数的作用
构造函数,我们应该叫他构造初始化函数,构造函数存在的意义就是初始化类的成员函数,它的出现替代了“直接初始化成员变量(成员变量得是public类型的)”与“间接使用类的成员函数初始化成员变量(类的成员变量初始化函数得是public类型的)”这两种不太安全的初始化成员函数的方式,使得初始化成员函数更加智能,可以根据输入参数的多少来进行初始化。而且一般的错误都是由于未初始化,或者初始化错误导致的,构造函数可以很好的解决这一点。
为何说“用成员函数初始化成员变量”和“直接初始化成员变量”这两种方式不安全?
构造函数,初始化成员变量的成员函数与直接初始化成员变量这三种方式都可以初始化成员变量,但是我如果说“每个Cstudent类的对象必须进行初始化,不初始化就报错”,那除了构造函数,其他两种方式都不能做到这一点。
三种不同的初始化成员变量的形式
用成员函数初始化成员变量:
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
private: // 不明确的声明访问限定符的话,系统默认为private类型
int mark;
string name;
public:
void init(int mark, string name) // 用于初始化的成员函数
{
this->mark = mark;
this->name = name;
}
void out()
{
cout << this->mark << endl;
}
};
int main()
{
Cstudent student;
student.init(89, "超级霸霸强");
student.out();
}
对public类型的成员变量进行赋值初始化:
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
public:
int mark;
string name;
public: // 类中可以在任何地方进行多次相同的访问限定符声明
void out()
{
cout << this->mark << endl;
}
};
int main()
{
Cstudent student;
student.mark = 89; // 直接对public类型的成员变量进行赋值初始化
student.name = "超级霸霸强";
student.out();
}
用构造函数进行初始化:
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
private:
int mark;
string name;
public: // 类中可以在任何地方进行多次相同的访问限定符声明
Cstudent(int mark); // 对含有一个参数的构造函数进行声明
void out()
{
cout << this->mark << endl;
}
};
Cstudent::Cstudent(int mark)
{
name = "还未命名";
this->mark = mark;
}
int main()
{
Cstudent student(89.5);
/* 注意:这里我只定义了含有一个参数的构造函数,如果你定义时不初始化,或者你填入的参数不等于1个int类型的变量,如果不能强制类型转换成int型的变量编译器就会报错*/
student.out(); // 在屏幕上输出出89
}
构造函数应用实例
功能:实现输入不同个数的初始化参数都能初始化成功
程序实现:
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
private:
int mark;
string name;
public: // 类中可以在任何地方进行多次相同的访问限定符声明
Cstudent(int mark); // 对含有一个参数的构造函数进行声明
Cstudent(int mark, string name); // 对含有两个参数的构造函数进行声明
Cstudent(); // 对含无参数的构造函数进行声明
void out()
{
cout << this->mark << endl;
}
};
Cstudent::Cstudent(int mark)
{
name = "还未命名";
this->mark = mark;
}
Cstudent::Cstudent()
{
name = "还未命名";
this->mark = 0;
}
Cstudent::Cstudent(int mark,string name)
{
this->name = name;
this->mark = mark;
}
int main()
{
Cstudent student, student1(78,"超级霸霸强"), student2(99,"超级无敌霸霸强");
// 定义时不输入任何初始化参数就代表调用无参数的构造函数进行Cstudent对象的初始化
student.out(); // 在屏幕上输出出0
student1.out(); // 在屏幕上输出出78
student2.out(); // 在屏幕上输出出99
}
定义构造函数时的注意事项
① 构造函数是用来初始化成员变量的,不存在返回值更不同定于函数的返回值类型;
② 构造函数不需要用户调用,也不应该被用户调用(不是不能调用),它是对象建立的时候自动被系统调用,用来初始化刚刚建立的对象的;如下示例:
#include <iostream>
#include <string>
using namespace std;
class Cstudent
{
private:
int mark;
string name;
public: // 类中可以在任何地方进行多次相同的访问限定符声明
Cstudent(int mark); // 对含有一个参数的构造函数进行声明
Cstudent(int mark, string name); // 对含有两个参数的构造函数进行声明
Cstudent(); // 对含无参数的构造函数进行声明
void out()
{
cout << this->mark << endl;
}
};
Cstudent::Cstudent(int mark)
{
name = "还未命名";
this->mark = mark;
}
Cstudent::Cstudent()
{
name = "还未命名";
this->mark = 0;
}
Cstudent::Cstudent(int mark,string name)
{
this->name = name;
this->mark = mark;
}
int main()
{
Cstudent student, student1(78,"超级霸霸强"), student2(99,"超级无敌霸霸强");
// 定义时不输入任何初始化参数就代表调用无参数的构造函数进行Cstudent对象的初始化
student.out(); // 在屏幕上输出出0
student1.out(); // 在屏幕上输出出78
student2.out(); // 在屏幕上输出出99
student.Cstudent::Cstudent(); // 构造函数可以被调用,但是没什么用
}
③ 如果用户没有定义自己的类的构造函数,那么系统会自动生成一个默认的构造函数,只不过该构造函数的函数体是空的,也就是什么都不做。就是我们在无任何初始化的情况下调式所看到全是一些随机数和乱码。
用new动态申请空间后到底用是什么释放?delete还是delete[]?
#include <iostream>
using namespace std;
int main()
{
int *pstr = new int[2]{ 45,89 }; // 用new进行内存分配的时候,如果是数组要用子程序块进行初始化,而如果申请的是一个内存空间,那只需要用()包围即可
cout << *pstr - *(pstr + 1) << endl;
delete[] pstr;
// 对于动态申请的数组空间必须使用delete[]来进行内存的释放,如果使用的是delete也不会报错,但是只是会释放数组内首个元素的内存,释放不彻底,这样是不对的
}