构造函数有什么特征?如何判断一个函数是不是构造函数?
核心判断 3 条铁律同时全部满足才是构造函数✅ 规则 1函数名称 和 类名完全一模一样大小写必须完全相同✅ 规则 2没有返回值连 void 都不能写✅ 规则 3创建对象的时候编译器自动调用不能手动调用只要有一条不满足它就不是构造函数只是普通成员函数。完整示例代码#include iostream #include string using namespace std; class MobilePhone { public: // ✅ 构造函数同时满足3条特征 MobilePhone(string brand, int storage) { m_brand brand; m_storage storage; cout 【构造函数执行】新手机创建完成 endl; } // ❌ 普通成员函数名字和类名不一样不是构造函数 void showInfo() { cout 手机品牌 m_brand 存储 m_storage GB endl; } // ❌ 普通成员函数虽然名字和类名一样但是写了void返回值不是构造函数 void MobilePhoneTest() { cout 这只是普通函数不是构造函数 endl; } private: string m_brand; int m_storage; }; int main() { // 创建对象自动调用构造函数 MobilePhone phone1(华为, 256); phone1.showInfo(); // 普通函数需要手动调用不会自动执行 phone1.MobilePhoneTest(); return 0; }运行输出【构造函数执行】新手机创建完成 手机品牌华为存储256GB 这只是普通函数不是构造函数第一部分类里面代码逐词逐句拆解class MobilePhoneclassC 关键字用来定义一个类图纸模板。MobilePhone类名这个类的名字。判断构造函数就拿函数名和这个名字对比。{}大括号类里面所有代码写在这个范围里类结束末尾必须写};末尾分号不能漏掉。public:public访问修饰符代表下面写的函数对外公开main 主函数可以访问调用。MobilePhone(string brand, int storage) { m_brand brand; m_storage storage; cout 【构造函数执行】新手机创建完成 endl; }MobilePhone函数名字和类名 MobilePhone 完全一致满足第 1 条特征。函数最前面没有写任何返回类型没有 int、没有 void、没有 string满足第 2 条特征。(string brand, int storage)参数列表string brand形参 brand临时局部变量接收传入的手机品牌只在这个函数执行期间存在。int storage形参 storage临时局部变量接收传入存储容量。构造函数可以有参数也可以无参数。参数有无不影响它是不是构造函数。{}函数体。创建对象的一瞬间大括号内代码自动执行不需要手动调用满足第 3 条特征。m_brand brand;把传入的品牌赋值给当前对象的私有成员变量。m_storage storage;把传入的存储大小赋值给当前对象私有成员。cout ...打印提示文字。void showInfo() { cout 手机品牌 m_brand 存储 m_storage GB endl; }void返回类型说明这个函数有返回描述无返回。showInfo函数名和类名 MobilePhone 不相同不满足规则 1。 所以它是普通成员函数不是构造函数。必须手动调用才会执行创建对象不会自动运行。void MobilePhoneTest() { cout 这只是普通函数不是构造函数 endl; }void写了返回类型违反规则 2。函数名是MobilePhoneTest和类名MobilePhone不一样。哪怕名字很像只要不完全相同、或者写了返回值就不是构造函数需要手动调用。private: string m_brand; int m_storage;private私有访问修饰符下面的成员变量只能在当前类内部的函数访问main 函数不能直接读写。string m_brand;成员变量用来保存手机品牌。int m_storage;成员变量保存手机存储容量。第二部分 main 函数逐词拆解重点MobilePhone phone1(华为, 256);MobilePhone phone1(华为, 256);MobilePhone类名使用 MobilePhone 这个图纸创建对象。phone1对象名称。程序在内存开辟一块内存空间存放 phone1 这个手机对象。(华为, 256)实参传递给构造函数的形参 brand、storage。✅ 写这一行代码自动触发构造函数执行我们没有手动写phone1.MobilePhone(华为,256);。;分号C 语句结束标记。phone1.showInfo();phone1对象名字代表操作 phone1 这个实例。.点号成员访问运算符读作 “的”用来访问对象里面的成员函数。showInfo普通成员函数名字。()函数调用标记带括号代表执行函数代码。 普通成员函数必须手动调用才会执行。phone1.MobilePhoneTest();手动调用这个函数哪怕名字和类名近似也只是普通函数创建对象时不会自动运行。return 0;main 函数执行结束phone1 对象销毁程序结束。第三部分 完整执行流程一步一步跟着走程序运行进入 main 函数。执行MobilePhone phone1(华为, 256);① 在内存开辟 phone1 对象内存。 ② 编译器识别 MobilePhone 是构造函数自动调用。 ③ 实参 华为 传给 brand256 传给 storage。 ④ 执行函数体给成员变量赋值打印【构造函数执行】。 ⑤ 构造函数执行完毕临时变量 brand、storage 销毁。执行phone1.showInfo();手动调用普通函数打印手机信息。执行phone1.MobilePhoneTest();手动调用打印提示。return 0;main 结束phone1 对象销毁。第四部分 3 条判定规则总结判断是不是构造函数函数名 类名大小写完全一致MobilePhone 类构造函数名字必须是 MobilePhonemobilephone、MobilePhone1 都不行。无返回值最前面不能写 void、int、string 等任何返回类型❌void MobilePhone()→ 普通函数不是构造函数 ✅MobilePhone()→ 构造函数无参构造创建对象自动调用无法手动调用不能写phone1.MobilePhone();手动执行构造函数语法报错。补充构造函数可以重载。只要参数列表不同可以写多个构造函数所有构造函数名字都必须等于类名。第五部分常见错误示例帮你排坑// 错误1写了返回值不是构造函数 void MobilePhone() {} // 错误2名字和类名不一致不是构造函数 MobilePhoneCreate(string brand) {} // 正确无参构造函数满足3条规则 MobilePhone() { m_brand 未知品牌; }下面是关于构造函数的问题整理问题 1构造函数是不是都写在类里面✅是的构造函数属于类的成员函数必须定义在类里面或者类内声明、类外实现但依然属于这个类。构造函数是属于这个类的函数不属于全局函数所以一定和类绑定。两种写法直接写在类内部我们前面所有例子用的写法class MobilePhone { public: // 类里面直接写构造函数 MobilePhone(string brand, int storage) { m_brand brand; } private: string m_brand; };类内声明类外面写实现构造函数声明写在类里面函数代码写在外面仍然属于这个类class MobilePhone { public: MobilePhone(string brand, int storage); // 声明写在类内部 private: string m_brand; }; // 类外面写实现::代表属于MobilePhone这个类 MobilePhone::MobilePhone(string brand, int storage) { m_brand brand; }就算函数体写在外面声明必须写在类中它仍然是类的构造函数不会脱离类独立存在。问题 2第三条规则【创建对象自动调用不能手动调用】怎么判断能不能直接看代码一眼看出来一句话回答单看函数本身代码是看不出第 3 条规则的。第 1、2 条是【写在函数头上的语法特征可以一眼静态看代码识别】第 3 条是【运行行为特征要结合代码调用场景才能判断】。拆解 3 条铁律的区别规则 1函数名和类名相同→ ✅ 看代码就能直接看出来静态特征规则 2没有返回值不能写 void→ ✅ 看代码就能直接看出来静态特征只要同时满足规则 1 规则 2编译器就认定它是构造函数编译器就会自动触发规则 3 的行为也就是说1、2 是身份标记3 是这个身份自带的行为结果。通俗理解规则 1、2 就像身份证看身份证就能识别你是谁。 规则 3 就像这个人自带的行为识别出身份之后才会有这个行为。不是写了一段代码标记 “自动调用”只要满足 12编译器自动赋予它【创建对象自动执行禁止手动调用】的特性。例程演示逐句逐词讲解看第三条规则#include iostream #include string using namespace std; class MobilePhone { public: // 满足规则1名字MobilePhone和类名一样 // 满足规则2前面没有任何返回类型没有void MobilePhone(string brand, int storage) { m_brand brand; m_storage storage; cout 【构造函数执行】自动运行 endl; } void showInfo() { cout 品牌 m_brand endl; } private: string m_brand; int m_storage; }; int main() { // 场景1创建对象自动调用构造函数规则3的行为 MobilePhone phone1(华为,256); phone1.showInfo(); // 场景2尝试手动调用构造函数直接编译报错 // phone1.MobilePhone(苹果,128); // 这一行放开注释编译器报错不能手动调用 return 0; }运行输出【构造函数执行】自动运行 品牌华为代码逐词拆解class MobilePhoneclass关键字定义类。MobilePhone类名。用来和里面的函数名比对判断规则 1。public: MobilePhone(string brand, int storage) { m_brand brand; m_storage storage; cout 【构造函数执行】自动运行 endl; }MobilePhone函数名和类名完全一致 → 满足规则 1。函数开头没有写 int/void/string等返回类型 → 满足规则 2。编译器看到这两条直接判定这是构造函数。 判定成功后自动生效规则 3只要创建 MobilePhone 对象就自动执行这个函数代码里不能手动调用它。(string brand, int storage)参数列表接收创建对象传入的数据。{}函数体自动执行里面代码。void showInfo() { cout 品牌 m_brand endl; }void写了返回类型名字和类名不一样是普通成员函数。普通函数必须手动写phone1.showInfo()才能运行没有自动调用特性。int main() { MobilePhone phone1(华为,256);MobilePhone类名创建 phone1 对象。phone1对象名开辟内存。(华为,256)传入参数。✅这里就是规则 3 的体现我们没有手动写调用语句编译器自动执行构造函数。// phone1.MobilePhone(苹果,128);❌ 尝试手动调用构造函数直接编译报错。普通成员函数可以这样调用构造函数不允许这就是规则 3 的限制。phone1.showInfo();手动调用普通成员函数正常执行。return 0; }main 结束对象销毁。问题 3函数声明的类内声明、类外实现是什么意思一句话核心 在类里面只写函数声明告诉编译器存在这个构造函数函数的代码主体实现写到类的外面。 虽然代码写在类外面但是它依然属于这个类的构造函数3 条铁律依旧全部生效完整示例代码#include iostream #include string using namespace std; // 定义类 MobilePhone class MobilePhone { public: // 【类内构造函数声明】 // 只告诉编译器MobilePhone这个类有一个构造函数接收string和int两个参数 // 这里不写函数体{}只是声明 MobilePhone(string brand, int storage); // 普通成员函数同样类内声明类外实现用来对比理解 void showInfo(); private: string m_brand; int m_storage; }; // 【类外构造函数的实现】 // MobilePhone:: 作用域解析符号 :: // 含义这个MobilePhone函数属于 MobilePhone 这个类 MobilePhone::MobilePhone(string brand, int storage) { // 这是构造函数的函数体 m_brand brand; m_storage storage; cout 【类外实现的构造函数执行】对象创建完成 endl; } // 【类外普通成员函数的实现】 void MobilePhone::showInfo() { cout 手机品牌 m_brand 存储 m_storage GB endl; } int main() { // 创建对象自动调用【类外实现的构造函数】 MobilePhone phone1(华为, 256); phone1.showInfo(); MobilePhone phone2(小米, 512); phone2.showInfo(); return 0; }程序运行输出【类外实现的构造函数执行】对象创建完成 手机品牌华为存储256GB 【类外实现的构造函数执行】对象创建完成 手机品牌小米存储512GB逐词逐句拆解讲解class MobilePhoneclassC 关键字定义一个类。MobilePhone类名。{}类的范围大括号里面只能放声明不放构造函数代码。末尾};分号不能丢。public: MobilePhone(string brand, int storage);public:公开访问权限。MobilePhone函数名字和类名完全一样满足构造函数规则 1。前面没有返回值没有 void满足构造函数规则 2。(string brand, int storage)参数列表。;分号重点这里只有声明没有{}函数体意思就是我告诉编译器这个类有这个构造函数但是函数的代码写在类外面别的地方。 ✅ 只要类内声明满足规则 1、2它就是构造函数。void showInfo();普通成员函数的声明。void代表返回类型函数名和类名不一致不是构造函数后面同样类外写实现。private: string m_brand; int m_storage;私有成员变量只能被这个类的函数访问包括类外实现的构造函数。哪怕构造函数代码写在类外面它依然属于 MobilePhone 类所以它可以访问类里面的私有成员m_brand、m_storage。};类定义结束分号千万不能忘记新手高频踩坑点。MobilePhone::MobilePhone(string brand, int storage) { m_brand brand; m_storage storage; cout 【类外实现的构造函数执行】对象创建完成 endl; }这一段是重点类外实现的构造函数第一个MobilePhone类名::作用域解析运算符读作 “属于”MobilePhone::翻译后面这个函数属于MobilePhone这个类。第二个MobilePhone构造函数名必须和类名一致(string brand, int storage)参数列表必须和类内声明的参数列表完全一模一样参数类型、顺序要匹配。{}函数实现体真正执行的代码写在这里。m_brand brand;给对象私有成员赋值打印输出重点记忆 类外写构造函数完整写法类名::类名(参数){函数体}void MobilePhone::showInfo() { cout 手机品牌 m_brand 存储 m_storage GB endl; }普通成员函数类外实现对比看差别返回类型 类名::函数名()构造函数没有返回类型所以开头直接写类名::类名()int main() { MobilePhone phone1(华为, 256);创建 phone1 对象。编译器找到 MobilePhone 类里面的构造函数声明然后找到外面对应的实现代码。自动调用构造函数规则 3 生效虽然函数体写在类外面创建对象依旧自动执行不能手动调用。phone1.showInfo();手动调用普通成员函数 showInfo。MobilePhone phone2(小米, 512);新建 phone2 对象再次自动调用同一个类外实现的构造函数。phone2.showInfo(); return 0; }执行流程梳理读到class MobilePhone编译器读取类里面的内容看到构造函数声明MobilePhone(string brand, int storage);登记这个类存在构造函数。继续往下读到类外面MobilePhone::MobilePhone(...)这就是这个构造函数的代码实现绑定到上面的声明。main 函数执行到MobilePhone phone1(华为, 256);开辟对象内存自动调用这个【类外实现】的构造函数运行大括号内代码对象创建完毕。为什么要这么写实际开发用处工程里常用头文件 (.h) 放类定义、函数声明源文件 (.cpp) 放函数实现.h头文件写 class 类只放各种函数声明构造函数声明也在这里给别人看接口。.cpp源文件写类外实现放函数具体代码实现细节藏在这里。大型项目就是这样拆分代码方便管理。验证 3 条铁律这个类外实现的构造函数全部满足✅规则 1函数名 MobilePhone和类名 MobilePhone 完全相同 ✅规则 2无返回值没有写 void ✅规则 3创建对象自动调用不能手动调用