目录
1. 构造函数不为人知的那些事
1.1 构造函数体赋值与初始化列表对比
1.2 explicit关键字与构造函数隐式转换
2. static成员
2.1 static成员的概念
2.2 static成员的特性与应用
2.3 小结
3. C++11 成员变量初始化新用法
4. 友元
4.1 友元函数
4.2 友元类
5. 内部类
5.1 内部类的概念及特性
前言: 在C++编程世界中,精深的语言特性和编码技巧对于编写出高效、可靠且易于维护的代码至关重要。本文将深度剖析C++中的五大关键特性:构造函数的秘密、static成员、C++11成员变量初始化新特性、友元函数与友元类,以及内部类的概念及其特性,并辅以丰富的代码示例和详尽的注解,力求帮助读者全方位理解并运用这些特性。
1. 构造函数不为人知的那些事
1.1 构造函数体赋值与初始化列表对比
在C++中,构造函数不仅可以通过其函数体给成员变量赋值,还可利用初始化列表进行初始化。二者的主要差异在于初始化列表会在构造函数体执行前优先完成初始化动作,尤其适用于引用、const成员以及无默认构造函数的自定义类型成员。
// 构造函数体赋值
class ExampleClass {
public:int value;ExampleClass(int val) {// 赋值操作发生在构造函数体内value = val; // 首先执行默认初始化,然后赋值}
};// 使用初始化列表
class ImprovedClass {
public:int value;ImprovedClass(int val) : value(val) { // 利用初始化列表直接初始化成员变量// 注意:此处value已经初始化完毕,无需额外赋值操作}
};
1.2 explicit关键字与构造函数隐式转换
在单参数构造函数前添加explicit
关键字,可以阻止编译器进行隐式类型转换构造,有利于消除潜在的二义性并提高代码清晰度。
class MyIntWrapper {
public:explicit MyIntWrapper(int v) : value(v) {} // 显示标记为显式构造函数
private:int value;
};void process(MyIntWrapper obj) {}int main() {int x = 10;// 下面的语句将编译失败,因为MyIntWrapper构造函数是显式的// process(x); // 错误:不允许隐式转换构造// 正确的做法:process(MyIntWrapper(x)); // 显式转换调用构造函数
}
2. static成员
2.1 static成员的概念
static成员变量和函数是与类绑定而非与类的实例关联的全局资源。它们在整个程序生命周期内只有一份拷贝,并可通过类名或作用域解析运算符(::)进行访问。
2.2 static成员的特性与应用
- static成员变量在整个程序中共享,且可在类外部初始化。
- static成员函数不含有`this`指针,因此不能访问非static成员,通常用于处理与类状态相关的全局功能。
class Counter {
public:static int count;Counter() { ++count; } // 每实例化一个对象,计数增加~Counter() { --count; } // 对象销毁时,计数减小static void displayCount() { // static成员函数展示当前对象数量std::cout << "Total objects created: " << count << std::endl;}private:static int count; // 声明静态成员变量
};
// 在类外初始化静态成员变量
int Counter::count = 0;int main() {Counter c1;Counter c2;Counter::displayCount(); // 直接通过类名调用静态成员函数
}
2.3 小结
static成员适用于存储跨对象共享的数据,以及提供与类状态紧密相关的全局功能,但需要注意线程安全问题。
3. C++11 成员变量初始化新用法
C++11引入了类内部成员变量的初始化新语法,允许在声明处直接给出默认值,虽非构造函数初始化列表的一部分,但简化了成员变量初始化的过程。
1class ModernClass {
2public:
3 int value {5}; // C++11 引入的成员变量初始化方式,默认值为5
4};
4. 友元
4.1 友元函数
友元函数是不受类访问限制的非成员函数,能够直接访问类的私有和保护成员。友元关系的建立增强了代码间的交互能力,但应谨慎使用以保持类的封装性。
class Circle {double radius;friend void printRadius(const Circle& c); // 声明printRadius为友元函数
public:Circle(double r) : radius(r) {}
};void printRadius(const Circle& c) {std::cout << "Circle's radius is: " << c.radius << std::endl; // 直接访问私有成员
}int main() {Circle circle(10);printRadius(circle); // 友元函数正常调用
}
4.2 友元类
友元类允许一个类的所有成员函数可以访问另一个类的私有和保护成员,增强了类间通信和协作的能力。
class A;
class B {friend class A; // B声明A为友元类
private:int b_value;
};class A {
public:void accessB(B& b_instance) {std::cout << "B's private member: " << b_instance.b_value << std::endl;}
};int main() {B b_obj;b_obj.b_value = 42; // 只有B的成员函数或友元类A能访问b_valueA a_obj;a_obj.accessB(b_obj); // 类A可以通过友元关系访问B的私有成员
}
5. 内部类
5.1 内部类的概念及特性
内部类是在另一个类定义内部定义的类,它能够直接访问外部类的所有成员,包括私有和保护成员。内部类可以强化类的封装性,实现逻辑模块化,降低耦合度。
class Outer {
public:class Inner {public:void accessOuter(Outer& outer) {std::cout << "Outer's private member: " << outer.privateValue << std::endl;}};private:int privateValue {10};
};int main() {Outer outer;Outer::Inner inner;inner.accessOuter(outer); // 内部类可以访问外部类的私有成员
}
总结: 通过深入探讨C++构造函数的各种微妙之处、static成员的使用场景和规则、C++11中成员变量初始化的创新方法,以及友元函数和友元类的应用和内部类的概念,我们得以窥见C++语言强大而灵活的一面。熟练掌握这些特性将极大地提升我们的编程技能,让我们能够编写出更加优雅、高效且安全的C++代码。同时,务必谨记适度使用这些特性,避免过度破环类的封装性和代码的可维护性。