【C++】类与对象(四)——初始化列表|explicit关键字|static成员|友元|匿名对象
温馨提示:这篇文章已超过438天没有更新,请注意相关的内容是否还可用!
前言:
初始化列表,explicit关键字,static成员,友元,匿名对象
文章目录
- 一、构造函数的初始化列表
- 1.1 构造函数体内赋值
- 1.2 初始化列表
- 二、explicit关键字
- 三、static成员
- 四、友元
- 4.1 友元函数
- 4.2 友元类
- 五、内部类
- 六、匿名对象
一、构造函数的初始化列表
1.1 构造函数体内赋值
class Date{ public: Date(int year, int month, int day){ //赋值,并非初始化 _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };构造函数调用之后,在函数体中给成员变量赋值,但这并不能称为初始化,因为初始化是在变量或对象的创建时进行的,如果有初始化,那么仅有一次只有一次,而构造函数体内可以多次赋值。
对于某些类型的成员变量,必须进行初始化。函数体内并不能满足这些类型的成员变量进行初始化,因此有了初始化列表的概念。
1.2 初始化列表
初始化列表用于在构造函数中初始化类成员变量的语法结构:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
_year _month _day被year,month,day进行初始化
Date(int year, int month, int day) : _year(year), _month(month), _day(day) { //函数体内其他操作 }-
实际上,即使没有显式写出初始化列表,成员变量依然会走初始化列表,但是因为没有初始值,因此成员变量是默认值。且初始化列表的顺序是成员变量声明的顺序。
-
以下成员,必须放在初始化列表位置进行初始化
- 引用成员变量
- const成员变量
- 自定义类型成员(且该类没有默认构造函数时)
class A{ public: A(int a):_a(a){ } private: int _a; }; class B{ private: A _aobj; // 自定义类型且没有默认构造函数 int& _ref; // 引用 const int _n; // const public: // _aobj(a)可以理解为调用A类的构造函数 B(int a, int ref):_aobj(a), _ref(ref), _n(0){ // 其他操作 } }; int main() { B b(10,5); return 0; } -
成员变量声明时提供缺值
当成员变量没有在初始化列表初始化时,成员变量被默认初始化为缺省值。
class Date{ public: Date(int year, int month, int day) : _month(month), _day(day) { //函数体内其他操作 } private: int _year = 1; int _month; int _day; }; int main() { //B b(); Date d(2024, 1, 31); return 0; }
通常初始化列表与构造函数体内赋值混合使用。
二、explicit关键字
-
单参数构造函数可以支持隐式类型的转换。
意思是允许通过给定类型的单一参数将对象从一种类型转换为另一种类型,而无需显式调用构造函数。
class Distance { private: double meters; public: // 单参数构造函数,允许从 double 类型隐式转换为 Distance 类型 Distance(double m) : meters(m) {} }; int main() { // 隐式类型转换:double 到 Distance Distance d1 = 10.5; // 显式类型转换也是可行的 Distance d2 = Distance(15.2); return 0; }在这个例子中,Distance 类具有一个单参数构造函数,允许将 double 类型的值隐式转换为 Distance 类型。当我们使用 Distance d1 = 10.5; 时,编译器会自动调用单参数构造函数,将 10.5 隐式转换为 Distance 类型的对象 d1。
-
C++11及之后的标准中,引入了一种新的特性,即“允许多参数的构造函数用于隐式类型转换”
例如:
class MyClass { public: // 多参数的构造函数 MyClass(int x, double y) { // 构造函数逻辑 std::cout // 隐式类型转换,调用构造函数 MyClass obj = {42, 3.14}; return 0; } } public: // 构造函数,用于增加 count MyClass() { count++; } int& GetCount() { return count; } private: // 静态数据成员 static int count; }; // 初始化静态数据成员 int MyClass::count = 0; int main() { // 创建对象,增加 count MyClass obj1; MyClass obj2; // 访问静态数据成员 std::cout public: // 静态成员函数,用于加法运算 static int add(int a, int b) { return a + b; } }; int main() { // 调用静态成员函数 int result = MathOperations::add(3, 5); std::cout private: int privateData; public: MyClass(int data) : privateData(data) {} // 声明友元函数 friend void displayPrivateData(const MyClass&); }; // 定义友元函数 void displayPrivateData(const MyClass& obj) { std::cout MyClass obj(42); displayPrivateData(obj); // 友元函数可以访问私有成员 return 0; } private: int privateMember; // 将 FriendClass 声明为友元类 friend class FriendClass; public: MyClass(int data) : privateMember(data) {} }; class FriendClass { public: void accessPrivateMember(const MyClass& obj) { // 友元类可以访问 MyClass 的私有成员 int data = obj.privateMember; } }; int main() { MyClass a(10); FriendClass b; b.accessPrivateMember(a); return 0; } private: int outerPrivate; public: class Inner { public: void display(const Outer& outer) { std::cout } void callInner() { Inner inner; inner.display(*this); } }; int main() { //通过callInner调用display Outer outerObj(42); outerObj.callInner(); //创建inner对象调用display Outer::Inner innerObj; innerObj.display(outerObj); return 0; } public: void display() { std::cout // 创建匿名对象,并调用其成员函数 MyClass().display(); return 0; }
-



