承接上篇C++57个入门知识点_19_ 构造函数的作用及写法(作用:用于对象初始化,定义时候就定义对象初值;写法:函数名是类名;不写函数返回值;参数可以有也可以没有;使用:CStudent stu(“张三“),本篇对构造函数进行更深入的介绍。
总结:
1.构造函数按照参数类型可以进行调用(无参、一个参数及两个参数的构造函数调用方法);
2.构造函数允许函数重载;
3.类的默认构造函数:如果类中一个构造函数都没有,编译器会提供一个默认的构造函数(无参的构造,可能会被优化不被使用)
4.C++语法中的关键字:explicit、=default、=delete
CStudent stu("张三");
,不允许隐式转换 CStudent stu="张三"
;隐式转换的方式就无法编译通过;=default
:显示指出使用默认的构造函数,增加可读性=delete
:表示禁止使用某函数(删除)#include
class CStudent {
public:
//构造函数
CStudent(const char* pszName) {
strcpy_s(m_szName, pszName);
}
void SetName(char* pszName)
{
strcpy_s(m_szName,pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc,char* argv[])
{
CStudent stu("张三");
return 0;
}
CStudent() {...}
,则其调用可以直接为 CStudent stu;
#include
class CStudent {
public:
//一个参数的构造函数,因为调用时使用的为常量参数,因此使用const
CStudent(const char* pszName) {
printf("CStudent(char* pszName)\r\n");
}
void SetName(char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu("张三");//一个参数的构造调用
CStudent stu="张三";//一个参数的构造调用,一种隐式转换的含义
return 0;
}
其调用方式为:CStudent stu("张三");
或 CStudent stu="张三";
#include
class CStudent {
public:
//两个参数的构造函数,因为调用时使用的为常量参数,因此使用const
CStudent(int nStuID, const char* pszName) {
printf("CStudent(int nStuID, char* pszName)\r\n");
}
void SetName(char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
//2个参数的构造调用
CStudent stu(1,"张三");
CStudent stu=CStudent(1,"张三");
return 0;
}
其调用为:CStudent stu(1,"张三");
或者CStudent stu=CStudent(1,"张三");
如果想类的对象想构造成没有参数,一个参数和两个参数等多个类型的,也就是函数名不变的情况下,可以有多种不同参数的形式,怎么去做呢?使用函数重载。
函数重载部分请参考:C++57个入门知识点_12 函数重载及其条件(函数重载:同一作用域中有多个同名函数、条件:(1)函数名相同(2)参数个数不同、类型不同、顺序不同(3)返回值和调用约定不考虑(4)作用域相同)
上面的代码也就变为下面的形式:
#include
class CStudent {
public:
//无参构造函数
CStudent() {
printf("CStudent()\r\n");
}
//一个参数的构造函数,因为调用时使用的为常量参数,因此使用const
CStudent(const char* pszName) {
printf("CStudent(char* pszName)\r\n");
}
//两个参数的构造函数,因为调用时使用的为常量参数,因此使用const
CStudent(int nStuID, const char* pszName) {
printf("CStudent(int nStuID, char* pszName)\r\n");
}
void SetName(char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu1;//无参的构造调用
CStudent stu2("张三");//一个参数的构造调用
CStudent stu2="张三";//一个参数的构造调用,一种隐式转换的含义
//2个参数的构造调用
CStudent stu3(1,"张三");
CStudent stu3=CStudent(1,"张三");
return 0;
}
如果类中一个构造函数都没有,编译器会提供一个默认的构造函数(无参的构造,可能会被优化不被使用)
之前我们在使用不存在构造函数的类的时候也是可以编译通过的,代码如下:
#include
class CStudent {
public:
void SetName(const char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu1;//无参的构造调用
return 0;
}
但是当你使用存在一个参数的构造函数,再进行无参构造调用就无法通过
#include
class CStudent {
public:
//一个参数的构造函数
CStudent(const char* pszName) {
printf("CStudent(char* pszName)\r\n");
}
void SetName(const char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu1;//无参的构造调用
return 0;
}
在后期的C++的标准中提供了一些关键字explicit、=default、=delete
CStudent stu("张三");
,不允许隐式转换 CStudent stu="张三"
;隐式转换的方式就无法编译通过。
CStudent stu="张三"
类似于将“张三”
这个变量赋给CStudent类型的stu
,这是一种隐式转换的写法
以下代码,由于使用了explicit关键字,就无法使用隐式转换的方式调用构造函数:
#include
class CStudent {
public:
//一个参数的构造函数
explicit CStudent(const char* pszName) {
printf("CStudent(char* pszName)\r\n");
}
void SetName(const char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu="张三";//一个参数的构造调用,一种隐式转换的含义
return 0;
}
运行结果如下:
当调用使用CStudent stu(“张三”)显示调用就可以通过
=default
:显示指出使用默认的构造函数,增加可读性
#include
class CStudent {
public:
CStudent() = default; //显示指出,创建默认的构造函数
void SetName(const char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu1;//无参的构造调用
return 0;
}
=delete
:表示禁止使用某函数(删除)
#include
class CStudent {
public:
CStudent() = delete;//删除默认的构造函数,编译器不会创建默认的构造函数
void SetName(const char* pszName)
{
strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
}
private:
int m_nStudID;//学号
char m_szName[255];//255个字节的缓冲区,姓名
};
int main(int argc, char* argv[])
{
CStudent stu1;//无参的构造调用
return 0;
}
5.学习视频地址:C++57个入门知识点_20_ 构造函数的调用