C++ 面向对象 - 对象定义方法汇总
C++对象定义方法汇总
1. 栈上定义方式
1.1 调用无参构造函数的定义方式
无参构造函数有两种:
- 默认无参构造函数
Demo(){}
- 默认值列表构造函数。
Demo():a{1},b{2}{} // 使用初始化列表实现
对象定义方式:
Demo d;
Demo d1{};
// 以下定义方式还调用了拷贝构造函数
Demo d2 = Demo();
Demo d3 = Demo{};
🚫 注意事项:
- 一个类只能有一个无参构造函数:无参构造函数的参数列表都为空,无法实现函数重载。
- 不能使用
对象名()
调用无参构造函数。 - 可以使用
类名()
的方式创建对象。 - 推荐使用花括号定义对象。
示例
class Demo1{
public:// 无参构造函数Demo(){cout << "无参构造函数"}
}class Demo2{
private:int a;int b;
public:// 默认值列表构造函数Demo():a{1},b{2}{cout << "默认值列表构造函数"<< endl;}
}int main()
{// 栈变量Demo1 d1; // 调用无参构造函数Demo2 d2{}; // 调用无参构造函数Demo1 d3 = Demo1();Demo2 d4 = Demo2{};// Demo2 d3(); // 错误
}
1.2 调用有参构造函数的定义方式
有参构造函数通过不同的参数列表进行重载。一个类中可以存在多个有参构造函数。
有参构造函数也可以使用参数默认值简化重载。包括兼并无参构造函数。
有参构造函数定义:
Demo(int a, int b):a(a),b(b){}
带默认值的有参构造函数定义:
Demo(int a = 1):a(a),b(1){}
此有参构造函数兼并无参构造函数,若定义了无参构造函数则会起冲突。
对象定义方式:
调用有参构造函数的对象定义通过()
或{}
来传递参数。
主流推荐使用{}
。
Demo d(2);
Demo d1{2, 3};
// 以下定义方式还调用了拷贝构造函数
Demo d2 = Demo(2, 3);
Demo d3 = Demo{2};
示例:
#include <iostream>
using namespace std;class Demo{
private:int a;int b;
public:// 带默认值的有参构造函数,可替代无参构造函数Demo(int a = 1):a{a},b{2}{cout << "带默认值的有参构造函数"<< endl;}// 初始化列表构造函数Demo(int a, int b):a{a},b{b}{cout << "初始化列表构造函数"<< endl;}
};int main()
{// 栈变量Demo d1; // 有参构造函数Demo d2{3}; // 有参构造函数Demo d3{3, 4}; // 初始化列表构造函数Demo d4(3, 4); // 初始化列表构造函数Demo d5 = Demo(2); // 有参构造函数Demo d6 = Demo{2}; // 有参构造函数Demo d7 = Demo(2,6); // 初始化列表构造函数Demo d8 = Demo{2,6}; // 初始化列表构造函数return 0;
}
1.3 调用拷贝构造函数的定义方式
拷贝构造函数是在用同类对象来定义新对象时调用。已经规定死了它的函数名和参数列表,所以不存在重载,一个类也只有一个拷贝构造函数。
拷贝构造函数定义:
Demo(const Demo& d):a{d.a},b{d.b}{}
对象定义方式:
拷贝构造函数是一种有参构造函数,遵循有参构造函数的对象定义方式。也有一种独特的定义方式:=
Demo d1; // 要先存在一个用来拷贝的对象
Demo d2(d1);
Demo d3{d1};
Demo d4 = d1; // 对象定义时,= 号调用的是拷贝构造函数
Demo d4 = Demo(); // 通过临时对象来定义新对象
示例:
#include <iostream>
using namespace std;class Demo{
private:int a;int b;
public:// 带默认值的有参构造函数,可替代无参构造函数Demo(int a = 1):a{a},b{2}{cout << "带默认值的有参构造函数"<< endl;}// 拷贝构造函数Demo(const Demo& d):a{d.a},b{d.b}{cout << "拷贝构造函数"<< endl;}
};int main()
{// 栈变量Demo d1; // 有参构造函数// 拷贝构造函数Demo d11(d1);Demo d12{d1};Demo d13 = d1;Demo d2 = Demo(2); // 有参构造函数Demo d3 = Demo{2}; // 有参构造函数return 0;
}
2. 堆上定义方式
堆上定义对象主要通过堆操作符new
来实现,它返回一个对象指针。
1.1 调用无参构造函数的定义方式
Demo *pd = new Demo; // 无参构造函数Demo *pd10 = new Demo[2]; // 无参构造函数,返回对象数组Demo *pd2 = new Demo(); // 无参构造函数Demo *pd3 = new Demo{}; // 无参构造函数
1.2 调用有参构造函数的定义方式
Demo *pd4 = new Demo(1); // 有参构造函数
Demo *pd5 = new Demo{1}; // 有参构造函数
1.3 调用拷贝构造函数的定义方式
Demo d1;
Demo *pd1 = new Demo(d1);
Demo *pd2 = new Demo{d1};
3. 总结
对象定义方式有两大类:
- 对象名:
类名 对象名
; - 类名:
类名()
;
对象定义的三小类: - 无参构造:可无符号、可带
()
和{}
。变量名不能带()
,类名可以带()
- 有参构造:可通过
()
、{}
传递参数。 - 拷贝构造:由
()
、{}
、=
传递同类对象参数。
对象定义是指对象第一次创建,构造函数只会在对象第一次创建的时候调用,若是已有对象使用了与对象定义相似的格式,必定不会调用构造函数。
4. 综合示例
#include <iostream>
using namespace std;class Demo{
private:int a;int b;
public:// 无参构造函数
// Demo(){cout << "无参构造函数"}// 默认值列表构造函数Demo():a{1},b{2}{cout << "无参构造函数"<< endl;}// 有参构造函数Demo(int a):a{a},b{2}{cout << "有参构造函数"<< endl;}// 初始化列表构造函数Demo(int a, int b):a{a},b{b}{cout << "初始化列表构造函数"<< endl;}// 拷贝构造函数Demo(const Demo& d):a{d.a},b{d.b}{cout << "拷贝构造函数"<< endl;}// 赋值运算符重载Demo& operator=(const Demo& d){cout << "赋值运算符重载"<< endl;if(this == &d) return *this;a = d.a;b = d.b;return *this;}
};int main()
{// 栈变量Demo d; // 无参构造函数Demo d1{}; // 无参构造函数Demo d2{3}; // 有参构造函数Demo d3{3, 4}; // 初始化列表构造函数Demo d4(3, 4); // 初始化列表构造函数Demo d5 = Demo(); // 无参构造函数Demo d6 = Demo{}; // 无参构造函数Demo d7 = Demo(2); // 有参构造函数Demo d8 = Demo{2}; // 有参构造函数Demo d9 = Demo(2,6); // 初始化列表构造函数Demo d10 = Demo{2,6}; // 初始化列表构造函数// 堆变量Demo *pd = new Demo; // 无参构造函数Demo *pd10 = new Demo[2];Demo *pd2 = new Demo(); // 无参构造函数Demo *pd3 = new Demo{}; // 无参构造函数Demo *pd4 = new Demo(1); // 有参构造函数Demo *pd5 = new Demo{1}; // 有参构造函数Demo *pd6 = new Demo(1, 2); // 初始化列表构造函数Demo *pd7 = new Demo{1, 2}; // 初始化列表构造函数// 拷贝构造函数Demo d11(d4);Demo d12{d4};Demo d13 = d3;Demo *pd8 = new Demo(d4);Demo *pd9 = new Demo{d4};// 赋值运算符重载d11 = d3;*pd9 = d4;return 0;
}