【C++】类的构造函数

类的构造函数

1. 作用:

只要新建对象,类的构造函数都会被自动调用(对象不能主动调用构造函数)

构造函数专门用来新建对象的
实际应用:用来初始化对象

2.语法规则:

类名(形参列表)

{

代码

}

示例代码:构造函数语法

cpp 复制代码
#include <iostream>

using namespace std;

class Animal
{
public:
    // 定义动物的构造函数
    Animal()
    {
        cout<<"动物的构造函数"<<endl;
    }
    
private:
    /* data */

};

int main(int argc, char const *argv[])
{
    //创建三个对象
    //创建几个对象,构造函数就自动调用几次
    Animal a1, a2, a3;
    //错误的:对象不可以自己来调用构造函数 error: invalid use of 'Animal::Animal'
    // a1.Animal();
    return 0;
}

/*
执行结果:
    动物的构造函数
    动物的构造函数
    动物的构造函数
*/

2.1 特点:

  • 构造函数的名字必须跟类名相同
  • 构造函数没有返回值类型
  • 如果程序员没有定义构造函数,系统会自动生成一个无参的构造函数

默认构造函数:

Animal()

{

什么事情都不做,只创建对象,分配空间

}

如果程序员自定义构造函数(无论是否带参数),那么系统就不会再自动生成默认的构造函数

示例代码:自定义了构造函数,系统不会再生成默认构造函数

cpp 复制代码
#include <iostream>

using namespace std;

/*
    构造函数用途:用来初始化对象里的数据
    如果程序员自定义构造函数(无论是否带参数),那么系统就不会再自动生成默认的构造函数
*/

class Animal
{
public:
    // 通过Animal的构造函数对Animal的属性设置
    Animal(int _age)
    {
        age = _age;
        cout<<"动物的带参数构造函数被调用了"<<endl;
        cout<<"age:"<<age<<endl;
    }
    
    
private:
    int age;
};

int main(int argc, char const *argv[])
{
    //正确,创建Animal的对象
    Animal a1(5);
    // 错误的,程序员写了带参数的构造函数,因此系统不会再生成无参构造函数,若要排除该错误,需自定义一个无参构造
    // 编译错误信息--》error: no matching function for call to 'Animal::Animal()'
    Animal a2; 
    return 0;
}

/*
执行结果:
    动物的带参数构造函数被调用了
    age:5
*/
  • 构造函数可以重载,重载构造函数是为了实现创建对象的多样化

示例代码:构造函数重载

cpp 复制代码
#include <iostream>

using namespace std;

/*
   构造函数可以重载,重载构造函数是为了实现创建对象的多样化
*/

class Animal
{
public:
    // 通过Animal的构造函数对Animal的属性设置
    Animal(int _age)
    {
        age = _age;
        cout<<"Animal(int _age)构造函数被调用了"<<endl;
        // cout<<"age:"<<age<<endl;
    }
    Animal()
    {
        cout<<"Animal()构造函数被调用了"<<endl;
    }
    Animal(string name)
    {
        cout<<"Animal(string name)构造函数被调用了"<<endl;
    }
    Animal(int _age, string name)
    {
        cout<<"Animal(int _age, string name)构造函数被调用了"<<endl;
    }
private:
    int age;
};

int main(int argc, char const *argv[])
{
    //创建Animal的对象
    Animal a1(5);
    Animal a2;
    Animal a3("you");
    Animal a4(18, "you");
    return 0;
}

/*
执行结果:
    Animal(int _age)构造函数被调用了
    Animal()构造函数被调用了
    Animal(string name)构造函数被调用了
    Animal(int _age, string name)构造函数被调用了
*/

3.构造函数常见的写法

3.1 无参构造函数

Animal()

3.2 带参数的构造函数

\quad 参数的类型以及个数没有任何限制,只要是合法的参数类型都可以作为构造函数的形参

3.3 带默认参数的构造函数

注意:这种版本的构造函数容易跟其它版本的构造函数起冲突(参数可以传递也可以不传递,就会跟无参构造或者其他版本的有歧义)

示例代码:带默认参数的构造函数

cpp 复制代码
#include <iostream>

using namespace std;

/*
    带默认参数的构造函数
*/

class Cat
{
public:
    //天下无敌的版本
    Cat(string _name="旺财",int _age=0)
    {
        name=_name;
        age=_age;
        cout<<"猫的构造函数带默认参数被调用了"<<endl;
    }

    void show()
    {
        cout<<"姓名: "<<name<<endl;
        cout<<"年龄: "<<age<<endl;
    }

private:
    int age;
    string name;
};

int main(int argc,char **argv)
{
    //创建猫的对象
    Cat c2;
    Cat c3("阿福");
    Cat c4("阿黄",5);
    
    c2.show();
    c3.show();
    c4.show();
    return 0;   
}

/*
执行结果:
    猫的构造函数带默认参数被调用了
    猫的构造函数带默认参数被调用了
    猫的构造函数带默认参数被调用了
    姓名: 旺财
    年龄: 0
    姓名: 阿福
    年龄: 0
    姓名: 阿黄
    年龄: 5
*/

这种版本的构造函数如果定义在类的外面,默认参数不需要写

cpp 复制代码
class Cat
{
public:
    Cat(int _age=5);

};
Cat::Cat(int _age) //定义在类的外面不需要写默认参数
{

}

示例代码:带默认参数的构造函数写在类的外面

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;

/*
    带默认参数的构造函数写在类的外面
*/

class Cat
{
public:
    // 默认参数写在声明处
    Cat(string _name="旺财",int _age=0);
    
    void show()
    {
        cout<<"姓名: "<<name<<endl;
        cout<<"年龄: "<<age<<endl;
    }

private:
    int age;
    string name;
};

Cat::Cat(string _name,int _age) //默认参数在类的外面不能写
{
    name=_name;
    age=_age;
    cout<<"猫的构造函数带默认参数被调用了"<<endl;
}

int main(int argc,char **argv)
{
    //创建猫的对象
    Cat c2;
    Cat c3("阿福");
    Cat c4("阿黄",5);
    
    c2.show();
    c3.show();
    c4.show();
    return 0;    
}

3.4 带参数列表的构造函数

注意:这种版本的构造函数如果定义在类的外面,需要这么写

cpp 复制代码
class Animal
{
public:
    Animal(int _age); //声明的时候不要写成参数列表
private:
    int age;
    其他类 对象obj;
};

Animal::Animal(int _age):age(_age) //定义的时候写成参数列表
{
    cout<<"构造函数"<<endl;
}

示例代码:带参数列表的构造函数

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;

/*
    带参数列表的构造函数
*/

class Cat
{
public:
    Cat(string _name,int _age):name(_name),age(_age)  //name=_name  age=_age
    //带默认参数和参数列表形式混合
    //Cat(string _name="旺财",int _age=0):name(_name),age(_age)
    {
        cout<<"带参数列表的构造函数"<<endl;
    }
    
    void show()
    {
        cout<<"姓名: "<<name<<endl;
        cout<<"年龄: "<<age<<endl;
    }

private:
    int age;
    string name;
};


int main(int argc,char **argv)
{
    //创建猫的对象
    Cat c1("阿黄",5);
    
    c1.show();
    return 0;    
}

3.5 指定父类的构造函数

\quad 子类指定父类的构造函数(如果不指定,默认情况下编译器总是调用父类的无参构造)

子类构造(形参列表):父类构造(传递给父类的实参)

{

}

示例代码:子类指定父类的构造函数

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;

/*
    默认情况下:创建子类,都是调用父类的无参构造
                程序员想要指定调用父类的某个版本的构造,该如何实现?
                    
*/
class Animal
{
public:
    Animal()
    {
        cout<<"父类Animal无参构造了"<<endl;
    }
    Animal(int m)
    {
        cout<<"父类Animal带int类型参数构造了,参数是: "<<m<<endl;
    }
};
class Cat:public Animal
{
public:
    Cat():Animal(123)
    {
        cout<<"子类Cat无参构造了"<<endl;
    }
    Cat(int n)
    {
        cout<<"子类Cat带int参数构造了"<<endl;
    }
    Cat(int n,string name):Animal(1258)
    {
        cout<<"子类Cat带int和string参数构造了"<<endl;
    }
};

int main(int argc,char **argv)
{
    Cat c1;
    Cat c2(666);
    Cat c3(888,"旺财");
    return 0;   
}

/*
执行结果
    父类Animal带int类型参数构造了,参数是: 123   ----->在子类构造函数进行指定
    子类Cat无参构造了
    父类Animal无参构造了
    子类Cat带int参数构造了
    父类Animal带int类型参数构造了,参数是: 1258 ----->在子类构造函数进行指定
    子类Cat带int和string参数构造了
*/

4.构造函数的调用

  • 写法一:

    Animal a; //注意:写成Animal a()这样子不正确,编译没有错,但是不会调用无参构造函数

    但是:Animal *p=new Animal() //这两种都可以调用无参构造函数

    Animal *p=new Animal; //这两种都可以调用无参构造函数

  • 写法二:

    Animal a(15);

  • 写法三:

    Animal a=Animal(15); //初始化语句

  • 写法四:

    Animal a;

    a=Animal(18); //赋值语句 Animal(18)会创建一个临时对象,然后把临时对象赋值给a

  • 写法五:

    Animal a={"小黄",5}; C++11列表初始化

    Animal b {"旺财",7};

    Animal c {};

相关推荐
Ronin3056 分钟前
【C++】类型转换
开发语言·c++
mrbone1122 分钟前
Git-git worktree的使用
开发语言·c++·git·cmake·worktree·gitab
浪裡遊33 分钟前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
真实的菜40 分钟前
JVM类加载系统详解:深入理解Java类的生命周期
java·开发语言·jvm
代码讲故事1 小时前
多种方法实现golang中实现对http的响应内容生成图片
开发语言·chrome·http·golang·图片·快照·截图
虾球xz2 小时前
CppCon 2018 学习:EFFECTIVE REPLACEMENT OF DYNAMIC POLYMORPHISM WITH std::variant
开发语言·c++·学习
Allen_LVyingbo2 小时前
Python常用医疗AI库以及案例解析(2025年版、上)
开发语言·人工智能·python·学习·健康医疗
小哈龙2 小时前
裸仓库 + Git Bash 搭建 本地 Git 服务端与客户端
开发语言·git·bash
G探险者2 小时前
《如何在 Spring 中实现 MQ 消息的自动重连:监听与发送双通道策略》
java·开发语言·rpc
weixin_437398213 小时前
转Go学习笔记
linux·服务器·开发语言·后端·架构·golang