【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 {};

相关推荐
一只小小汤圆1 分钟前
c# 显示正在运行的线程数
开发语言·c#
vvilkim1 小时前
深入理解C# MVVM模式:从理论到实践
开发语言·c#
magic 2451 小时前
return this;返回的是谁
java·开发语言
egoist20231 小时前
【Linux仓库】冯诺依曼体系结构与操作系统【进程·壹】
linux·运维·服务器·开发语言·操作系统·冯诺依曼体系结构
快乐肚皮1 小时前
深入解析Java17核心新特性(密封类、模式匹配增强、文本块)
开发语言·java17·密封类·模式匹配增强·文本块
钟离墨笺2 小时前
Go语言学习-->编译器安装
开发语言·后端·学习·golang
why1512 小时前
百度golang研发一面面经
开发语言·golang
钟离墨笺3 小时前
Go语言学习-->从零开始搭建环境
开发语言·后端·学习·golang
whoarethenext3 小时前
使用 C++/OpenCV 图像直方图比较两个图片相似度
开发语言·c++·opencv·直方图·相似度对比
csdndenglu4 小时前
QT 5.9.2+VTK8.0实现等高线绘制
开发语言·qt