C++的构造函数、默认构造函数和=default

本文详细介绍了C++中的默认构造函数,包括编译器自动生成的情况和程序员显式定义的情况。当定义了带参数的构造函数时,编译器不再提供默认构造函数,导致无法创建无参数的对象。通过使用= default,可以在已有构造函数的情况下显式要求编译器生成默认构造函数,确保可以初始化成员变量。文章通过案例展示了如何使用= default解决编译错误,并解释了为何需要这样做。
摘要由CSDN通过智能技术生成

目录

1. 基本概念

2. 为什么要加=default?

3. 参考资料


1. 基本概念

构造函数(contructor)是特殊的成员函数,其作用是控制对象的初始化,初始化类的数据成员。默认构造函数的必要充分条件是

  1. 构造函数

  2. 无参

默认构造函数分两种:

     一种是按照C++定义类的规则由编译器自动生成的,即:如果没有显示(隐式的)的定义默认的构造函数,则编译器会为类合成一个默认构造函数。在定义一个类的时候,如果没有定义任何一个构造函数,编译器会为我们生成一个默认构造函数,为了便于理解,案例1如下:

案例1. 默认构造函数

// files: sales_data.h
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <string>
using namespace std;

class SalesData
{
   string sale_isbn;

};
#endif
//用户文件main.cpp
#include "sales_data.h"
#include <iostream>

int main()
{
    std::cout << "SalesData totoal before..." << std::endl;
    SalesData total;
    std::cout << "SalesData totoal after..." << std::endl;

    return 0;
}
g++ main.cpp -I. -o a.out

   编译通过。

  另一种就是手动的,程序员为类定义一个的无参构造函数,即是默认构造函数

可能你会有一些疑问:什么时候会调用默认构造函数呢?

答案是,程序员写 到如下样式的程序时会调用默认构造函数。

类名 类变量; //类变量后面没有括号,没有传入实参等等。

如案例1中 SalesData total;就调用了默认构造函数

    那么,=default与默认构造函数是什么关系呢?

     默认构造函数去掉函数体,在参数列表括号后面加上=default;来显式的要求编译器合成一个函数体,默认初始化成员变量,这样形成的类似声明的程序语句,起到的作用和默认构造函数是一样的。=default既可以声明在类的内部,也可以作为定义出现在类的外部。如果出现在类的内部,表明默认构造函数是内联的,如果出现在类的外部,则表明此构造函数不是内联的。

2. 为什么要加=default?

《C++ primer》第五版讲到

=default 来要求编译器生成默认构造函数,仅仅是因为我们既需要其他形式的构造函数,也需要默认的构造函数。

        如果我们定义了构造函数 ,则编译器就不会再生成默认构造函数了。案例2说明如下:

案例2. 自定义带参数的构造函数,编译不过

将案例1中的类稍微修改一下,实现案例2

//sales_data.h
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <string>
using namespace std;

class SalesData
{
 public:
   SalesData(string a_sale_isbn);

 private:
   string sale_isbn;

};

#endif

用户程序和编译方法和案例1相同,但是,编译报错了。

 g++ main.cpp -I. -o a.out
In file included from main.cpp:1:0:
sales_data.h:10:20: error: expected ‘)’ before ‘a_sale_isbn’
    SalesData(sring a_sale_isbn);
                    ^~~~~~~~~~~
goodstudy@xgoodstudyVPCEG27YC sales_data (study) $ g++ main.cpp -I. -o a.out
main.cpp: In function ‘int main()’:
main.cpp:7:15: error: no matching function for call to ‘SalesData::SalesData()’
     SalesData total;
               ^~~~~
In file included from main.cpp:1:0:
sales_data.h:10:4: note: candidate: SalesData::SalesData(std::__cxx11::string)
    SalesData(string a_sale_isbn);
    ^~~~~~~~~
sales_data.h:10:4: note:   candidate expects 1 argument, 0 provided
sales_data.h:7:7: note: candidate: SalesData::SalesData(const SalesData&)
 class SalesData
       ^~~~~~~~~
sales_data.h:7:7: note:   candidate expects 1 argument, 0 provided
sales_data.h:7:7: note: candidate: SalesData::SalesData(SalesData&&)
sales_data.h:7:7: note:   candidate expects 1 argument, 0 provide

   所以,有带参数的构造函数被定义式,而你正好有需求调用默认构造函数,此时你必须自定义一个默认构造函数。此时,你其实有两种自定义默认构造函数。

  1. 上述所说的=default的方式

  2. 自定义一个无参构造函数

    案列3将采用=default的方式解决案列2中的编译问题,并且打印处初始化值。以下是具体的案例。

案列3. =default解决有参构造函数存在时编译不过的问题

//sales_data.h
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <string>
#include <iostream>
using namespace std;

class SalesData
{
 public:
    SalesData() = default;
    SalesData(string sale_a):sale_isbn(sale_a)
    {
    }
    void GetSaleBn()
    {
          cout << "sales_isbn:" << sale_isbn << endl;
    }

 private:
   string sale_isbn;

};

#endif
//main.cpp

#include "sales_data.h"
#include <iostream>

int main()
{
    std::cout << "SalesData totoal before..." << std::endl;
    SalesData total;
    total.GetSaleBn();
    std::cout << "SalesData totoal after..." << std::endl;

    return 0;
}
xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ g++ main.cpp -I. -o a.out
xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ls
a.out  log.log  main.cpp  Makefile  sales_data.cpp  sales_data.h
xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) $ ./a.out 
SalesData totoal before...
sales_isbn:
SalesData totoal after...
xuehaiyang@xuehaiyang-VPCEG27YC sales_data (study) 

编译和结果如上所示,字符串类型的成员变量被初始化为空字符串了。

3. 参考资料

《C++ primer》第五版

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青草地溪水旁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值