类的构造函数
- [1. 作用:](#1. 作用:)
- 2.语法规则:
-
- [2.1 特点:](#2.1 特点:)
- 3.构造函数常见的写法
-
- [3.1 无参构造函数](#3.1 无参构造函数)
- [3.2 带参数的构造函数](#3.2 带参数的构造函数)
- [3.3 带默认参数的构造函数](#3.3 带默认参数的构造函数)
- [3.4 带参数列表的构造函数](#3.4 带参数列表的构造函数)
- [3.5 指定父类的构造函数](#3.5 指定父类的构造函数)
- 4.构造函数的调用
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 {};