跳到主要内容
C++ 类与对象进阶:类型转换、静态成员、友元及内部类 | 极客日志
C++
C++ 类与对象进阶:类型转换、静态成员、友元及内部类 C++ 类与对象进阶特性涵盖类型转换机制、静态成员变量与函数的存储访问规则、友元函数与类的权限突破、嵌套类的作用域独立性以及匿名对象的生命周期管理。重点解析构造函数隐式转换与 explicit 关键字的使用场景,静态成员的全局共享性与生命周期,友元关系的单向性,内部类作为独立作用域的特性,以及匿名对象在函数传参中的临时性应用。
赛博行者 发布于 2026/2/9 更新于 2026/5/31 20 浏览前言
本文将进一步探讨类与对象的进阶特性,在已有构造函数、拷贝构造函数、析构函数、操作符重载和初始化列表的基础上,重点分析以下核心内容:类型转换、static 成员、友元函数、内部类、匿名对象。
一、利用构造函数的类型转换
在 C++ 中,构造函数不仅仅是用来初始化对象的,它还定义了'如何将其他类型的数据转换为当前类类型'的规则。
1.1 内置类型转换为自定义类型
**隐式转换原理:**如果一个自定义类中包含一个只接受一个参数的构造函数(或者除第一个参数外,其余参数都有默认值),那么编译器就可以把这个参数的类型,隐式地转换为该类的对象。
**代码演示场景:**你写了一个 Integer 类,它有一个接受 int 的构造函数。
#include <iostream>
using namespace std;
class Integer {
public :
Integer (int v) : value (v) {
cout << "构造函数被调用:int -> Integer" << endl;
cout << "value:" << value << endl;
}
private :
int value;
};
int main () {
Integer a (10 ) ;
cout << "-------------------------------" << endl;
Integer b = 20 ;
return 0 ;
}
代码逻辑:
Integer b = 20 在老标准中等价于 Integer temp(20) + Integer b(temp)。
首先调用构造函数完成对临时对象 temp 的初始化 -> 调用拷贝构造函数将 temp 拷贝给对象 b(即先生成临时对象再进行拷贝构造)。
但在现代 C++ 编译器优化下,直接等同于 Integer b(20)。
#include <iostream>
using namespace std;
class Complex {
public :
Complex (double r) : real (r), imag (0.0 ) {
cout << "调用转换构造函数:double -> Complex" << endl;
}
void print () {
cout << real << " + " << imag << "i" << endl;
}
private :
double real;
double imag;
};
void printComplex (Complex c) {
c.print ();
}
int main () {
printComplex (5.1 );
return 0 ;
}
1.2 explicit 关键字 虽然隐式转换很方便,但它有时会引发意外的错误或降低代码可读性。
例如:如果 Array(int size) 构造函数被隐式调用,Array a = 10 看起来像是把 a 赋值为 10,但实际上它的逻辑可能是创建了一个大小为 10 的数组,这很容易产生误解。
class MyString {
public :
explicit MyString (int n) : length(n) { }
private :
int length;
};
void func (MyString s) {}
int main () {
MyString s2 (10 ) ;
MyString s3 = MyString (10 );
func (static_cast <MyString>(10 ));
return 0 ;
}
**温馨提示:**对于单参数构造函数,除非你有非常明确的理由允许隐式转换(例如数学类型 Complex 从 double 转换),否则通常建议加上 explicit 以增加类型安全性。
1.3 特殊情况与细节
A. 多参数但有默认值 如果一个构造函数有多个参数,但除了第一个参数外,其余参数都有默认值,它依然被视为'转换构造函数',可以触发隐式转换。
class Data {
public :
Data (int a, int b = 0 ) {}
};
int main () {
Data d = 5 ;
return 0 ;
}
B. C++11 列表初始化 在 C++11 之后,如果构造函数接受多个参数,可以使用花括号 {} 进行隐式转换(这被称为列表初始化),explicit 同样可以禁止这种行为。
class Point {
public :
Point (int x, int y) {}
};
void draw (Point p) {}
int main () {
Point a = { 5 , 5 };
draw ({ 1 , 2 });
return 0 ;
}
1.4 类型转换的使用场景 **场景示例:*C++ 标准库的 string 就是最好的例子,它的构造函数接受 const char ,允许隐式转换。
#include <iostream>
#include <string>
using namespace std;
void printMessage (const string& msg) {
cout << "Message: " << msg << endl;
}
int main () {
printMessage ("Hello World" );
string s = "C++" ;
return 0 ;
}
**场景示例:**假设你写了一个处理超大整数的类 BigInt
class BigInt {
public :
BigInt (int n) { }
friend BigInt operator +(const BigInt& lhs, const BigInt& rhs) { ; }
};
int main () {
BigInt a = 100 ;
BigInt b = a + 50 ;
return 0 ;
}
二、static 成员 在 C++ 中,静态成员变量是一种特殊的类成员,与普通的成员变量不同,它们不属于类的某个具体对象,而是属于整个类。
这意味着,无论你创建了多少个该类的对象,静态成员变量在内存中只有一份拷贝,所有对象共享这一份数据。
2.1 声明与定义 (关键痛点) 这是最容易出错的地方,静态成员变量通常需要在类内声明,在类外定义 / 初始化。
A. 类内声明 class MyClass {
private :
static int sharedCount;
};
B. 类外定义
int MyClass::sharedCount = 0 ;
类外定义时不需要再写 static 关键字。
静态成员变量不能在声明位置给缺省值初始化,因为静态成员变量不属于某个对象,不走构造函数初始化列表。
2.2 访问静态成员变量
通过类名访问 (推荐): 这是最标准的方式,明确表示该变量属于类。
MyClass::sharedCount
通过对象访问: 语法上允许,但容易引起误解(让人以为是实例变量)。
obj.sharedCount
请注意:静态成员作为类的成员,同样受 public、protected、private 访问权限的限制。
核心规则:
Public: 可以通过 ClassName::value 在任何地方访问。
Private: 不能在类外通过 ClassName::value 访问(除非是友元)。
Protected: 不能在类外通过 ClassName::value 访问(除非是子类)。
#include <iostream>
using namespace std;
class Server {
private :
static int port;
public :
static int status;
};
int Server::port = 8080 ;
int Server::status = 1 ;
int main () {
cout << "服务器状态:" << Server::status << " (允许)" << endl;
Server::status = 0 ;
return 0 ;
}
2.3 静态成员函数 定义如下:用 static 修饰的成员函数,称之为静态成员函数,静态成员函数没有 this 指针。
静态成员函数能够访问其他静态成员,但无法访问非静态成员,因为缺少 this 指针的支持。
非静态成员函数可以自由访问所有静态成员变量和静态成员函数。
#include <iostream>
using namespace std;
class RuleTester {
public :
static int staticVar;
int normalVar;
RuleTester (int v) : normalVar (v) {}
static void helperStatic () {}
static void staticFunc () {
cout << "[静态函数] 正在运行" << endl;
cout << " -> 访问 staticVar: " << staticVar << " (成功)" << endl;
helperStatic ();
}
void normalFunc () {
cout << "[普通函数] 正在运行 (对象:" << this << ")" << endl;
cout << " -> 访问 normalVar: " << normalVar << " (成功)" << endl;
cout << " -> 访问 staticVar: " << staticVar << " (成功)" << endl;
staticFunc ();
}
};
int RuleTester::staticVar = 100 ;
int main () {
std::cout << "=== 场景 1: 静态函数调用示例 ===" << std::endl;
RuleTester::staticFunc ();
std::cout << "\n=== 场景 2: 对象函数调用示例" << std::endl;
RuleTester obj (999 ) ;
obj.normalFunc ();
return 0 ;
}
2.4 static 的核心特点
唯一性 : 所有该类的实例对象共享同一个静态成员变量,修改其中一个对象的静态变量,会影响所有其他对象。
代码示例:验证静态成员变量的唯一性,实例对象的共享性。
class Box {
public :
Box (int id) : _id(id) { }
static int sharedValue;
int _id;
};
int Box::sharedValue = 0 ;
int main () {
Box box1 (1 ) ;
Box box2 (2 ) ;
cout << "=== 验证 1: 内存地址对比 (最直接的证据) ===" << endl;
cout << "box1.sharedValue 的地址:" << &box1. sharedValue << endl;
cout << "box2.sharedValue 的地址:" << &box2. sharedValue << endl;
cout << "box1.id (普通变量) 的地址:" << &box1. _id << " (属于 box1)" << endl;
cout << "box2.id (普通变量) 的地址:" << &box2. _id << " (属于 box2)" << endl;
if (&box1. sharedValue == &box2. sharedValue) {
cout << "-> 结论:地址相同,证明在内存中是同一份拷贝。" << endl;
}
cout << "\n=== 验证 2: 修改值行为测试 ===" << endl;
cout << "初始状态:" << std::endl;
cout << "box1 看 sharedValue = " << box1. sharedValue << endl;
cout << "box2 看 sharedValue = " << box2. sharedValue << endl;
cout << "\n[操作] 通过 box1 修改 sharedValue 为 999..." << endl;
box1. sharedValue = 999 ;
cout << "修改后:" << endl;
cout << "box1 看 sharedValue = " << box1. sharedValue << endl;
cout << "box2 看 sharedValue = " << box2. sharedValue << " <-- 也就是这里变了!" << endl;
return 0 ;
}
存储位置 : 存储在全局/静态存储区,而不是对象的内存空间(栈或堆)中,因此 sizeof(对象) 不包含静态成员的大小。
代码示例:验证静态成员不储存在对象的内存空间(堆 或 栈)
#include <iostream>
using namespace std;
class ClassWithoutStatic {
public :
int a;
};
class ClassWithStatic {
public :
int a;
static int b;
};
class OnlyStatic {
public :
static int c;
};
class Empty { };
int main () {
ClassWithoutStatic obj1;
ClassWithStatic obj2;
OnlyStatic obj3;
Empty obj4;
cout << "======= Sizeof 验证实验 ========" << endl;
cout << "int 的大小:" << sizeof (int ) << " 字节" << endl;
cout << "\n1. 对比有无静态成员:" << endl;
cout << "ClassWithoutStatic (只有 int a): " << sizeof (obj1) << " 字节" << endl;
cout << "ClassWithStatic (int a + static int b): " << sizeof (obj2) << " 字节" << endl;
cout << "\n2. 极端情况验证:" << endl;
cout << "OnlyStatic (只有 static int): " << sizeof (obj3) << " 字节" << endl;
cout << "Empty (空类): " << sizeof (obj4) << " 字节" << endl;
if (sizeof (obj1) == sizeof (obj2) && sizeof (obj3) == sizeof (obj4)) {
cout << "\n-> 结论验证成功:静态成员变量不占用对象的内存空间。" << endl;
} else {
cout << "\n-> 结论验证失败。" << endl;
}
return 0 ;
}
生命周期 : 从程序开始运行时分配内存,直到程序结束时释放,它独立于任何对象的生存期。
#include <iostream>
#include <string>
using namespace std;
class Tracer {
public :
Tracer (const string& n) : _name(n) { cout << "[内存分配] " << _name << " 已构造 " << endl; }
~Tracer () { cout << "[内存释放] " << _name << " 已析构 " << endl; }
private :
string _name;
};
class Box {
public :
static Tracer sharedResource;
Box () { cout << " -> Box 普通对象被创建 (构造函数)" << endl; }
~Box () { cout << " -> Box 普通对象被销毁 (析构函数)" << endl; }
};
Tracer Box::sharedResource ("静态成员变量 (Static)" ) ;
int main () {
cout << "\n========== main 函数开始 ==========" << endl;
cout << "准备进入局部作用域创建对象..." << endl;
{
Box localBox;
cout << "局部 Box 对象正在使用..." << endl;
}
cout << "局部作用域已结束,Box 对象已死。" << endl;
cout << "但请注意:静态成员还活着" << endl;
cout << "========== main 函数结束 ==========\n" << endl;
return 0 ;
}
2.5 静态成员变量的使用 经典样例:利用静态成员变量来统计当前有多少个对象存活。
#include <iostream>
using namespace std;
class Student {
public :
static int studentCount;
Student () {
++studentCount;
}
~Student () {
--studentCount;
}
};
int Student::studentCount = 0 ;
void test () {
Student s3;
cout << "局部对象 s3 存在时:" << Student::studentCount << endl;
}
int main () {
cout << "初始人数:" << Student::studentCount << endl;
Student s1;
Student s2;
cout << "创建两个对象后:" << Student::studentCount << endl;
test ();
cout << "局部对象 s3 销毁后,对象个数:" << Student::studentCount << endl;
return 0 ;
}
三、友元 C++ 中的友元 (Friend) 机制能够突破封装限制,使特定函数或类获得访问其他类私有 (private) 和保护 (protected) 成员的权限。
3.1 友元函数
友元函数不是类的成员函数,但在类中声明时加上了 friend 关键字。
友元函数可以像成员函数一样,访问类中所有的成员变量(包括 private 和 protected)。
友元函数可以在类定义的任何地方声明,不受类访问限定符限制,但是定义通常在类外部。
一个函数可以是多个类的友元函数。
**运算符重载:**比如重载 << (输出运算符) 或 >> (输入运算符),通常需要访问类的私有数据,但这些运算符的左操作数通常是 cout 或 cin,而不是对象本身,所以必须定义为非成员函数(友元)。
当外部函数需要访问某个类的私有成员,而该函数并非该类的成员函数时。
**代码示例一:**假设有一个 Box 类,它的宽度是私有的,但我们想写一个外部函数来打印这个宽度。
#include <iostream>
using namespace std;
class Box {
double width;
public :
Box (double w) : width (w) {}
friend void printWidth (const Box& box) ;
};
void printWidth (const Box& box) {
cout << "Box 的宽度是:" << box.width << endl;
}
int main () {
Box box (10.0 ) ;
printWidth (box);
return 0 ;
}
**代码示例二:**定义一个复数类 Complex,包含实部 real 和虚部 imag(均为私有),并通过友元重载输入输出。
#include <iostream>
using namespace std;
class Complex {
friend ostream& operator <<(ostream& out, const Complex& c);
friend istream& operator >>(istream& in, Complex& c);
public :
Complex (int r = 0 , int i = 0 ) : real (r), imag (i) {}
private :
int real;
int imag;
};
ostream& operator <<(ostream& out, const Complex& c) {
out << "(" << c.real << " + " << c.imag << "i)" ;
return out;
}
istream& operator >>(istream& in, Complex& c) {
cout << "请输入实部和虚部:" ;
in >> c.real >> c.imag;
return in;
}
int main () {
Complex c1;
cin >> c1;
cout << "你输入的复数是:" << c1 << endl;
return 0 ;
}
细节深度解析:
参数顺序: operator<<(ostream& out, const Complex& c)。第一个参数 out 对应操作符 << 左边的 cout。第二个参数 c 对应操作符 << 右边的对象 c1。这就是为什么它不能是成员函数(成员函数要求左边必须是 this 也就是 Complex 对象)。
**返回类型 ostream&:**如果我们返回 void,那么 cout << c1 可以工作,但 cout << c1 << endl; 会报错。因为 cout << c1 执行完变成 void,接下来的 void << endl 是非法的。返回 out 的引用,使得 cout << c1 执行后返回 cout 本身,接着执行 cout << endl。
**输入时的引用:**在 operator>> 中,参数 Complex& c 必须没有 const,因为输入的目的就是修改这个对象的值。
3.2 友元类 **核心概念:**如果在类 A 中将类 B 声明为'友元',都那么类 B 中的所有成员函数可以访问类 A 的私有和保护成员。
简单理解为:这就好比你(类 A)给了你最好的朋友(类 B)一把你家(私有区域)的备用钥匙,其他人进不来,但你的朋友可以自由进出。
**基本语法:**在需要'授权'的类中,使用 friend 关键字声明另一个类。
代码示例:声明 ClassB 是 ClassA 的友元
class ClassA {
friend class ClassB ;
public :
ClassA (int val) : secretValue (val) {}
private :
int secretValue;
};
class ClassB {
public :
void accessSecret (const ClassA &a) {
cout << "ClassA 的私有数据是:" << a.secretValue << endl;
}
};
int main () {
ClassA a (10 ) ;
ClassB b;
b.accessSecret (a);
return 0 ;
}
3.3 友元成员函数 **核心概念:**只将另一个类的某个特定成员函数声明为友元,而不是整个类,这需要严格注意声明顺序,使用较少。
**场景演示:**假设 类 A 中的成员函数 func() ,需要访问 类 B 的内部私有数据。
我们要解决的问题是:
在类 B 中,我们需要声明 类 A 的 func() 函数是友元函数。
编译器读到 类 A 的 func() 时,需要知道 类 B 存在。
编译器读到 类 B 的 friend 声明时,需要知道 类 A 及其 func() 已经声明过。
正确的实现步骤:
**前向声明 类 B。**目的:告诉编译器 B 是一个类,因为 A 中会用到 B 的引用或指针。
**定义 类 A,并声明 成员函数,但不要写函数体。**目的:让编译器知道 A 里面有个函数叫 func,但不能写函数体是因为此时 B 的内部细节(私有成员)还不可见。
**定义 类 B,并在其中用 friend 声明 A 的特定函数。**目的:此时编译器已经知道 A 和 func 的存在,所以 friend 声明是合法的。
**定义 类 A 成员函数的函数体。**目的:此时 A 和 B 都已完全定义,函数体中可以自由访问 B 的私有成员。
**代码示例:**假设我们有两个类:Date (日期类,包含私有数据) 和 DatePrinter (打印机类) ,我们需要让打印机类中的 printDate 成员函数访问 Date 类的私有数据。
#include <iostream>
using namespace std;
class Date ;
class DatePrinter {
public :
void printDate (const Date& d) ;
void otherFunc (const Date& d) ;
};
class Date {
private :
int year, month, day;
public :
Date (int y, int m, int d) : year (y), month (m), day (d) {}
friend void DatePrinter::printDate (const Date& d) ;
};
void DatePrinter::printDate (const Date& d) {
cout << "Date: " << d.year << "-" << d.month << "-" << d.day << endl;
}
void DatePrinter::otherFunc (const Date& d) {
cout << "无法访问 Date 类的私有数据." << endl;
}
int main () {
Date dt (2023 , 10 , 1 ) ;
DatePrinter printer;
printer.printDate (dt);
printer.otherFunc (dt);
return 0 ;
}
3.4 友元的三个重要特性
单向性: 如果 A 是 B 的友元(A 可以访问 B),并不意味着 B 是 A 的友元(B 不能访问 A)。
不传递性: 如果 A 是 B 的友元,B 是 C 的友元,A 不是 C 的友元。
不能继承: 友元关系不能被子类继承。如果 A 是 B 的友元,A 的子类默认不是 B 的友元。
四、内部类
4.1 内部类的核心概念 **核心概念:**在 C++ 中,内部类通常被称为嵌套类,它是指如果一个类定义在另一个类的内部,那么这个类就叫做内部类。
**温馨提示:**内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
**代码示例:**定义外部类 Outer,在外部类 Outer 中定义嵌套类 Inner。
class Outer {
public :
Outer (int val) : outerData (val) { }
class Inner {
public :
Inner (int val) : innerData (val) {}
private :
int innerData = 200 ;
};
private :
int outerData = 100 ;
};
4.2 内部类的核心特性
作用域: 内部类的名字只在外部类的作用域内可见,如果在外部类之外使用它,必须使用作用域解析运算符 :: (例如 Outer::Inner)。
#include <iostream>
using namespace std;
class Outer {
public :
class Inner {
public :
void show () {
cout << "我是 Inner 类中的函数" << endl;
}
};
void funcInside () {
Inner in;
in.show ();
}
Inner createInner () {
Inner temp;
return temp;
}
};
int main () {
Outer::Inner obj2;
obj2. show ();
return 0 ;
}
关键点解析:
Inner in (在 Outer 内部):相当于在同一个文件夹下找文件,直接喊名字就行,不需要加前缀。
Outer::Inner obj2 (在 main 函数):相当于在根目录找深层文件夹里的文件,必须写出完整路径:文件夹/文件名。
:: 运算符:它的全称就是'作用域解析运算符',专门用来剥开类的'外壳'取里面的东西。
访问权限限制: 嵌套类本身可以是 public、protected 或 private 的,如果是 private,则只有外部类可以使用这个嵌套类。
#include <iostream>
using namespace std;
class Outer {
public :
class PublicInner {
public :
void show () {
cout << "我是 PublicInner,外面的人可以定义我的对象。" << endl;
}
};
private :
class PrivateInner {
public :
void show () {
cout << "我是 PrivateInner,只有 Outer 内部能用我。" << endl;
}
};
public :
void internalUse () {
cout << "--- 进入 Outer 内部函数 ---" << endl;
PublicInner pub;
pub.show ();
PrivateInner pri;
pri.show ();
}
};
int main () {
cout << "--- 在 main 函数中 ---" << endl;
Outer::PublicInner pubObj;
pubObj.show ();
Outer outerObj;
outerObj.internalUse ();
return 0 ;
}
独立性:
C++ 的嵌套类仅仅是类名嵌套在作用域里。
外部类的对象不包含嵌套类的对象(除非显式声明了成员变量)。
嵌套类的对象也不自动包含指向外部类对象的 this 指针,它就像是一个普通的类,只是名字被藏起来了。
1. '仅仅是类名嵌套在作用域里'
**含义:**这是一种组织代码的方式,而不是组合对象的方式,Outer 对于 Inner 来说,仅仅起到了一个命名空间的作用。
类比:
你有一个文件夹叫 Work(Outer)。
文件夹里有一个文件叫 Plan.doc(Inner)。
这个文件虽然放在文件夹里,但文件本身的内容并没有写着'我属于 Work 文件夹'。
文件夹本身也没有因为多了一个文件而变'重'(在 C++ 的类定义层面)
**总结:**这两个类独立存在,只是内部类被外部类通过作用域限制了。
2. '外部类的对象不包含嵌套类的对象'
**含义:**当你实例化 Outer 时,编译器不会自动帮你实例化 Inner,Outer 的内存大小(sizeof)只取决于 Outer 自己的成员变量,与 Inner 无关。
代码演示:外部类的对象不包含嵌套类的对象
#include <iostream>
using namespace std;
class Outer {
public :
int x;
class Inner {
public :
int y;
int z;
};
};
int main () {
Outer out;
cout << "Outer 的内存大小:" << sizeof (out) << endl;
return 0 ;
}
3. '嵌套类的对象也不自动包含指向外部类对象的 this 指针'
**含义:**在 C++ 中,Inner 的对象是一个孤立的个体,没有一条'隐形的线'连向外部类对象。
这就意味着:Inner 对象没有指向 Outer 类的 this 指针,在 Inner 类中无法直接访问 Outer 类的非静态成员变量,它找不到那个变量属于哪个对象。
代码示例:内部类 Inner 访问 外部类 Outer,需要传入 外部类 Outer 的对象
class Outer {
public :
int OuterData;
void Func () {
cout << "外部类 Outer 的函数:Func() 被调用了!" << endl;
}
public :
Outer (int val) : OuterData (val) {}
class Inner {
public :
void inspect (Outer& out) {
cout << "=== Inner 正在访问 Outer 类 ===" << endl;
cout << "外部类的成员变量:" << out.OuterData << endl;
out.Func ();
}
};
};
int main () {
Outer out (100 ) ;
Outer::Inner obj;
obj.inspect (out);
return 0 ;
}
内部类默认是外部类的友元类。
#include <iostream>
using namespace std;
class Outer {
private :
int secretCode;
void privateFunc () {
cout << "外部类 Outer 的私有函数:privateFunc() 被调用了!" << endl;
}
public :
Outer (int val) : secretCode (val) {}
class Inner {
public :
void inspect (Outer& out) {
cout << "Inner 正在访问..." << endl;
cout << "获取私有密码:" << out.secretCode << endl;
out.privateFunc ();
}
};
};
int main () {
Outer outerObj (999 ) ;
Outer::Inner innerObj;
innerObj.inspect (outerObj);
return 0 ;
}
五、匿名对象 在 C++ 中,匿名对象是指通过显式调用构造函数创建,但未被命名的临时对象。
5.1 匿名对象的核心概念
通过'类型'(实参) 创建的对象称为匿名对象
匿名对象:Person("Bob") (没有名字,直接调用构造函数)
通过'类型 对象名 (实参)'方式定义的对象称为有名对象
有名对象:Person p("Alice") (对象名为 p)
class Person {
public :
Person (string name) : _name(name) { cout << _name << "调用构造函数" << endl; }
private :
string _name;
};
int main () {
Person p ("Bob" ) ;
Person ("Alice" );
return 0 ;
}
5.2 匿名对象的特性 **核心特性:**匿名对象的生命周期通常只存在于创建它的那一行代码(当前表达式语句),一旦该行代码执行完毕,匿名对象会立即调用析构函数销毁。
#include <iostream>
#include <string>
using namespace std;
class Person {
public :
Person (string name) : m_Name (name) {
cout << " [构造] " << m_Name << " 出生了 (对象被创建)" << endl;
}
~Person () {
cout << " [析构] " << m_Name << " 挂掉了 (对象被销毁)" << endl;
}
private :
string m_Name;
};
int main () {
cout << "--- 开始测试有名对象 (Alice) ---" << endl;
Person p ("Alice" ) ;
cout << " Alice 依然存活" << endl;
cout << "--- 有名对象测试结束 ---\n" << endl;
cout << "--- 开始测试匿名对象 (Bob) ---" << endl;
Person ("Bob" );
cout << "此时代码运行到这里,Bob 早就挂了" << endl;
cout << "--- 匿名对象测试结束 ---" << endl;
return 0 ;
}
5.3 匿名对象的应用场景
A. 作为函数参数 (最常用) 如果一个对象只需要作为参数传递给函数,且之后不再使用,使用匿名对象可以减少代码行数,且不需要绞尽脑汁起变量名。
void doSomething (const string& s) {
cout << "Processing: " << s << endl;
}
int main () {
string str ("Hello" ) ;
doSomething (str);
doSomething (string ("Hello" ));
return 0 ;
}
B. 连续调用 class Solution {
public :
Solution () { }
void func () { }
};
int main () {
Solution s;
s.func ();
Solution ().func ();
return 0 ;
}
5.4 匿名对象与引用 (重要考点)
非 const 引用无法绑定匿名对象
C++ 规定:匿名对象是右值,普通的左值引用不能绑定右值
代码示例:
class A {
public :
A () { }
private :
int _val;
};
int main () {
}
const 引用可以绑定 (生命周期延长)
C++ 规定:如果一个匿名对象被绑定到一个 const 引用上,该匿名对象的生命周期会被延长,直到该引用变量的作用域结束。
代码示例:
class A {
public :
A () { }
private :
int _val;
};
int main () {
const A& r = A ();
}
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online