一、C++类中的构造函数
作用:初始化类中的数据成员。
思考:为什么要构造函数?
因为一个类的对象,被创建出来后,就应该立即可以调用这个类去执行任务。但是,有一些设备必须要初始化后才能够使用,例如:LCD屏幕,触摸屏等...所以这时候我们就要有一个函数去完成这些初始化任务。《构造函数》
二、构造函数的特点
1、函数名 与 类名 同名
2、函数没有返回值
3、函数在创建对象的时候自动调用 (不需要用户调用)
构造函数的语法:
class 类名
{
public:
类名(参数列表){
//初始化动作
}
}
//demo:
class base
{
public:
base() //构造函数
{
cout << "调用base的构造函数" << endl;
}
}
#include <iostream>
using namespace std;
//构造函数特点
//1、函数名 与 类名 同名
//2、函数没有返回值
//3、函数在创建对象的时候自动调用 (不需要用户调用)
class base
{
public:
base() //构造函数
{
cout << "base..." << endl;
}
};
int main()
{
//创建一个base类的对象b
base b;
return 0;
}
编译运行:
注意:构造函数,一定要定义在公共区(即public区),否则无法创建对象!
练习:设计一个学生类,里面包含:姓名,学号,班级。在构造函数中,初始化这些数据成员。并输出。
#include <iostream>
#include <string.h>
using namespace std;
class student
{
public:
student()
{
strcpy(name,"xiaowu");
id = 10086;
strcpy(clas,"gao yi 3 ban");
cout << name << endl;
cout << id << endl;
cout << clas << endl;
}
void show()
{
cout << name << endl;
cout << id << endl;
cout << clas << endl;
}
char name[1024];
int id;
char clas[100];
};
int main()
{
student a;
a.show();
return 0;
}
编译运行如下所示:
三、构造函数的参数传递
#include <iostream>
using namespace std;
class base
{
public:
//设计一个构造函数初始化 date
base(int d) //该构造函数含一个参数,在创建对象时,一定要传递参数,否则报错
{
date = d;
}
void show()
{
cout << date << endl;
}
private:
int date;
};
int main()
{
//创建对象
base a(10086);
a.show();
base b(10010);
b.show();
return 0;
}
编译运行:
练习:设计一个汽车类 car,里面包含车牌,价格,颜色,创建对象并传递参数初始化和输出。
#include <iostream>
#include <string.h>
using namespace std;
class car
{
public:
//设计一个构造函数
car(const char *id,int m,const char *c)
{
strcpy(car_id,id);
money = m;
strcpy(color,c);
}
void show()
{
cout << "车牌:" << car_id << endl;
cout << money << "元" << endl;
cout << "颜色:" << color << endl;
}
private:
char car_id[1024];
int money;
char color[1024];
};
int main()
{
//定义一辆汽车
car c("粤A666",169888,"黑色");
c.show();
//定义一辆汽车
car d("粤B8888",290000,"银色");
d.show();
return 0;
}
四、默认构造函数
当用户没有设计构造函数时,系统会自动生成一个无参的构造函数。
当用户设计构造函数后,系统就不会生成一个无参的构造函数。
#include <iostream>
using namespace std;
class base
{
public:
base()
{
//2、编写一个不带参数的构造函数!
cout << "无参构造函数" << endl;
}
base(int d)
{
//用户设计了一个构造函数,系统就不会自动生成无参构造函数
cout << "带参构造函数" << endl;
}
private:
int date;
};
int main()
{
base a; //调用系统自动生成的无参默认构造!!
//问题:不存在不带参数的构造函数,就无法调用。
//解决方法:1、传递一个参数给该对象,让它构造成功。
// 2、编写一个不带参数的构造函数!
//1、传递参数
base b(100);
return 0;
}
五、总结
当用户设计构造函数后,应该添加一个无参构造函数,防止对象构造失败。
六、构造函数重载
类中的构造函数也支持函数重载。
函数重载的方式:
1、函数名相同
2、函数的参数列表不同(参数个数不同,类型不同,或不同类型位置不同)
3、返回值不能作为重载的依据
#include <iostream>
using namespace std;
class base
{
public:
base() //构造默认函数,不带参数的就是默认构造
{
cout << "无参构造函数" << endl;
}
base(int a)
{
cout << "传递 int 参数构造函数:" << a <<endl;
}
base(const char *str)
{
cout << "传递 char *参数的构造函数:" << str << endl;
}
base(int a, const char *str)
{
cout << "传递int char *参数的构造函数" << a << str << endl;
}
};
int main()
{
//作用:方便用户创建对象
base a;
base b(10);
base c("hello");
base d(20,"nihao");
return 0;
}
七、构造函数的参数列表初始化
作用:在构造函数中利用参数列表进行初始化,简化初始化的流程。
注意:参数列表初始化只能在构造函数中使用,普通函数不行!!且这种初始化方式并不是《无敌》的。
对于用户自定义的数据类型无法进行参数列表初始化。例如数组。
#include <iostream>
#include <string.h>
using namespace std;
class stu
{
public:
/*
利用参数列表初始化
name = n 是错误的!!对于不能直接使用 = 号 赋值的数据,不能填写在参数列表中初始化!
stu(const char *n,int a,int h):name(n),age(a),Height(h)
{
cout << "调用参数列表初始化构造" << endl;
}
*/
//正确写法
stu(const char *n,int a,int h):age(a),Height(h)
{
cout << "调用参数列表初始化构造" << endl;
//手动赋值
strcpy(name,n);
}
private:
char name[100];
int age;
int Height;
}
int main()
{
//定义一个学生
stu a("小吴",18,175);
return 0;
}
练习
定义一个商品类,包含 商品名称,价格,数量,卡路里。利用参数列表初始化的方式,初始化这些数据,并设计接口输出。
#include <iostream>
#include <string.h>
using namespace std;
class Goods
{
public:
Goods()
{
}
Goods(const char *n,int m,int nu, const char *k):money(m),num(nu)
{
//手动赋值
strcpy(name,n);
strcpy(kcal,k);
}
void show()
{
cout << "name: " << name << endl;
cout << "kcal: " << kcal << endl;
cout << "num: " << num << endl;
cout << "money: " << money << endl;
}
private:
char name[100]; //商品名称
int money; //商品价格
int num; //商品数量
char kcal[100]; //商品卡路里
};
int main()
{
//定义一个苹果对象
Goods pg("apple",7,100,"100KCAL");
pg.show();
return 0;
}
编译运行:
八、new 与 malloc 的区别
#include <iostream>
#include <stdlib.h>
using namespace std;
class base
{
public:
base()
{
cout << "I am a parameterless constructor..." << endl;
}
base(int d):date(d)
{
cout << "I am a constructor with parameters..." << endl;
}
private:
int date;
};
int main()
{
//1、利用 malloc 分配 base 类的堆空间
//base *p = (base *)malloc(sizeof(base)); //不对调用构造函数
//2、利用 new 分配 base 类的堆空间
base *q = new base; //->调用无参构造函数(默认构造函数)
//3、利用 new 分配 base 类的堆空间,并传递参数
base *w = new base(10086); //->调用带参构造函数
return 0;
}
编译运行:
总结:new 会调用构造函数,malloc 不会调用,且new可以传递参数给构造函数。
练习
设计一个学生类,里面包含 姓名,学号,班级,利用参数列表初始化的方式初始化,并利用new的方式分配该对象的空间。再调用show接口显示信息。
#include <iostream>
#include <string.h>
using namespace std;
class student
{
public:
student(const char *n,int nu,const char *cl):num(nu)
{
//手动赋值
strcpy(name,n);
strcpy(clas,cl);
}
void show()
{
cout << "name:" << name << endl;
cout << "number:" << num << endl;
cout << "classes:" << clas << endl;
}
private:
char name[100]; //学生姓名
int num; //学生学号
char clas[100]; //学生班级
};
int main()
{
//利用 new 分配一个 student 类的对象空间
student *s = new student("xiaowu",12345,"Class 1, Grade 2, Senior High School");
s->show();
return 0;
}
编译运行: