构造函数:
以类名作为函数名
无返回值类型
定义:在c++中,有一种特殊的成员函数,它的名字和类名相同,没有返回值,不需要用户显示调用(也不能调用),而是在创建对象时自动执行,这就是构造函数
作用:
初始化对象的数据成员,一般使用构造函数进行成员变量的初始化
类对象被创建时,编译器为对象分配内存控件并自动调用析构函数以完成成员的初始化
种类:
无参构造
一般构造
拷贝构造
注意:
如果创建的类中未出现书写任何构造函数,系统会自动生成默认的无参构造函数(函数为空,什么都不做)
如果书写了构造函数,系统就不会在自动生成默认构造,如果希望有这样一个无参构造函数,需要自己显示的书写出来
带参构造:
类名::构造(类型1 参数1,类型2 参数2,...)
{
//相关初始化代码
}
#include<iostream>
using namespace std;
class Student{
private:
char *m_name;
int m_age;
float m_score;
public:
//声明构造函数:
Student(char *name,int age,float score);
//声明普通成员函数
void show();
};
//定义构造函数
Student::Student(char *name,int age,float score){
m_name=name;
m_age=age;
m_score=score;
}
//定义普通成员函数
void Student::show(){
cout<<m_name<<"年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
//创建对象时向构造函数传参
Student stu("小明",15,92.5);
stu.show();
//创建对象时向构造函数传参
Student *pstu=new Student("李华",16,98);
pstu->show();
return 0;
}
说明:
在Studet类中定义了一个构造函数Student(char* ,int ,float),它的作用是给三个private赋值,要想调用该构造函数,就得在创建对象的同时传递实参,并且实参由()包围,和普通函数调用非常类似
在栈上创建对象时,实参位于对象名后面
在堆上创建对象时,实参位于类名后面
构造函数必须时public属性的,否则创建对象时无法调用。设置成private、protect属性也不会报错,但是没有意思
构造函数要求:不管是声明还是定义,函数名前面都不能出现返回值类型,即使是多个void也不允许
函数体中不能有return语句
构造函数可以允许重载,一个类可以有多个重载的构造函数,创建对象时根据传递的实参来判断调用哪一个构造函数
构造函数的调用是强制性的,一旦在类中定义了构造函数,那么创建对象时一定要调用,如果有多个重载的构造函数,那么创建对象时提供的实参必须和其中的一个构造函数匹配,反过来说,创建对象时只有一个构造函数会被调用
#include<iostream>
using namespace std;
class Student{
private:
char *m_name;
int m_age;
float m_score;
public:
//声明构造函数:
Student();
Student(char *name,int age,float score);
//声明普通成员函数
void setname(char *name);
void setage(int age);
void setscore(float score);
void show();
};
//定义构造函数
Student::Student(){
m_name=NULL:
m_age=0;
m_score=0.0;
}
Student::Student(char *name,int age,float score){
m_name=name;
m_age=age;
m_score=score;
}
//定义普通成员函数
void Student::setname(char *name){
m_name = name;
}
void Student::setage(int age){
m_age = age;
}
void Student::setscore(float score){
m_score = score;
}
void Student::show(){
if(m_name==NULL||m_age<=0)
cout<<"成员变量还没初始化"<<endl;
else
cout<<m_name<<"年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
//创建对象时向构造函数传参
Student stu("小明",15,92.5);
stu.show();
//创建对象时向构造函数传参
Student *pstu=new Student();
pstu -> show();
pstu -> setname("李华");
pstu -> setage(16);
pstu -> setscore(96);
pstu->show();
return 0;
}
默认构造函数:
如果用户自己没有定义构造函数,那么编译器就会自动生成一个默认的构造函数,只是这个构造函数的函数体是空的,也没有形参,也不执行任何操作
Student (){}
一个类必须有构造函数,要么用户自己定义,那么编译器自动生成,一旦用户自己定义了构造函数,不管有几个,也不管形参如何,编译器都不再自动生成
调用没有参数的构造函数也可以省略括号
#include <iostream>
using namespace std;
class Student{
private:
char *m_name;
int m_age;
float m_score;
public:
Student(char *name, int age, float score);
void show();
};
//采用初始化列表
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
//TODO:
}
void Student::show(){
cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
Student stu("小明", 15, 92.5f);
stu.show();
Student *pstu = new Student("李华", 16, 96);
pstu -> show();
return 0;
}
class Student
{
public:
//构造函数的重载与普通函数重载相同
Student(); //默认构造
Student(string name,string desc);//带参构造
~Student();
void showInfo();
string GetName()
{
return m_name;
}
void SetName(string val)
{
m_name=val;
}
string Getdesc()
{
return m_desc;
}
int Getag()
{
return m_age;
}
void Setage(int val)
{
if(val<0)
m_age=18;
else
m_age=val;
}
private:
string m_Name;
string m_desc;
int m_age;
}
Student::Student()
{
cout<<"默认构造"<<endl;
}
Student::Student(string name, string desc)
{
m_Name=name; //等价写法 SetName(name);
m_desc=desc;
cout<<"带参构造"<<endl;
}
//等价于
Student::Student(string name, string desc):m_Name(name),m_desc(desc) //初始化参数列表
void Student::ShowInfo()
{
cout<<m_desc<<endl;
}
Student stu1; //在栈内存中直接分配空间
Student stu2("马化腾","普通家庭");
stu2.showinfo();
Student* stu=new Student("撒贝宁","北大还行"); //在堆内存中分配空间
stu->ShowInfo();
delect stu;
注意,成员变量的初始化顺序与初始化列表中列出的变量的顺序无关,它只与成员变量在类中声明的顺序有关
初始化const成员变量
构造函数初始化列表还有一个很重要的作用,那就是初始化const成员变量
初始化const成员变量的唯一方法就是使用初始化列表
class VLA{
private:
const int m_len;
int *m_arr;
public:
VLA(int len);
};
//必须使用初始化列表来初始化m_len
VLA::VLA(int len):m_len(len){
m_arr=new int[len];
}