一 static成员:
静态成员变量是属于整个类的,而不是某个特定对象的。也就是说,所有对象共享同一个静态成员变量。它的特点包括:
非静态成员变量:
class A
{
public:
int _x; // 非静态成员变量
};
int main()
{
A a1, a2;
a1._x = 5;
a2._x = 10;
std::cout << a1._x << std::endl; // 输出 5
std::cout << a2._x << std::endl; // 输出 10
return 0;
}
在这个例子中,a1
和 a2
是两个不同的对象,它们各自有自己的 _x
变量,互不影响。a1._x
的值是 5,而 a2._x
的值是 10。
静态成员变量:
class A
{
public:
static int _x; // 静态成员变量
};
// 在类外定义并初始化静态成员变量
int A::x = 0;
int main()
{
A a1, a2;
a1._x = 5;
std::cout << "a1._x: " << a1._x << std::endl; // 输出 5
std::cout << "a2._x: " << a2._x << std::endl; // 输出 5
a2._x = 10;
std::cout << "a1._x: " << a1._x << std::endl; // 输出 10
std::cout << "a2._x: " << a2.x << std::endl; // 输出 10
return 0;
}
在这个例子中,x
是静态成员变量,它属于类 A
,而不属于任何特定的对象。我们在类外定义并初始化了 A::x
。
总结:
共享性:静态成员变量在所有对象间共享,同一个类的所有实例都可以访问同一个静态成员变量。
类外初始化:静态成员变量必须在类外进行定义和初始化,确保它们只初始化一次。
静态成员函数:
特点:
没有 this 指针:静态成员函数不能访问类的非静态成员变量或成员函数,因为不属于任何特定的对象所以它们没有隐含的 this
指针。
类范围内的函数:静态成员函数属于类的范围,可以在没有对象实例的情况下调用,直接通过类名调用。
访问静态成员变量:静态成员函数可以访问静态成员变量,因为它们同样属于类范围内。
代码演示:
class A
{
public:
A()
{
++n;
}
A(const A& a)
{
++n;
}
static int Getn()
{
return n;
}
private:
static int n;
};
// 在类外定义并初始化静态成员变量
int A::n = 0;
int main()
{
A aa1;
A aa2;
cout << A::Getn() << endl;
return 0;
}
二 友元:
定义:
友元函数是一个定义在类外部的普通函数,但它被授予访问该类的私有和保护成员的特权。友元函数不是类的成员函数,但需要在类的内部声明,并使用 friend
关键字。
友元函数的特点:
-
友元函数可以访问类的私有和受保护成员,但它本身并不是类的成员函数。
- 友元函数在某种程度上是外部函数,但它们被赋予了访问指定类的私有和受保护成员的特权。
-
友元函数不能被
const
修饰。- 尽管友元函数可以访问类的内部成员,但它们依旧是外部函数,因此不受类的成员函数的约束,如
const
限定。
- 尽管友元函数可以访问类的内部成员,但它们依旧是外部函数,因此不受类的成员函数的约束,如
-
友元函数声明可以放在类的任何位置,不受访问控制符(如
public
、protected
或private
)的限制。- 无论是在
public
部分、protected
部分还是private
部分,友元函数声明都可以放置,不影响其访问权限。
- 无论是在
-
一个友元函数可以是多个类的友元。
- 这意味着同一个函数可以被多个类声明为友元,从而能够访问这些类的私有和受保护成员。
-
友元函数的调用与普通函数相同。
- 友元函数在调用时,不需要通过对象或类来调用,它们的调用方式与普通的非成员函数一致。
代码演示:
#include <iostream>
using namespace std;
class Point
{
public:
Point()
{
_x++;
}
// 友元函数声明
friend ostream& operator<<(ostream& out, const Point& p);
private:
static int _x;
};
// 初始化静态成员变量
int Point::_x = 0;
// 友元函数定义
ostream& operator<<(ostream& out, const Point& p)
{
out << Point::_x<<endl;
return out;
}
int main()
{
Point a;
cout << a << 3 <<endl; // 输出Point类的静态成员变量_x的值
//cout << 3 << endl; // 输出3
return 0;
}
友元类:
定义:
友元类在C++中是一个用于控制访问权限的重要机制。它们允许一个类的所有成员函数访问另一个类的私有和受保护成员。
代码演示:
class Time
{
friend class Date; // Date 类是 Time 类的友元类
public:
Time(int hour = 0, int minute = 0, int second = 0)
: _hour(hour), _minute(minute), _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year), _month(month), _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问 Time 类的私有成员变量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t; // Date 类中有一个 Time 对象
};
特点:
-
友元关系是单向的:
- 友元关系是单向的。比如,
Date
类可以访问Time
类的私有成员,但Time
类不能自动访问Date
类的私有成员。如果需要Time
类也能访问Date
类的私有成员,你必须在Time
类中声明Date
类为友元类。
- 友元关系是单向的。比如,
-
友元关系不能传递:
- 友元关系是不可传递的。即使
C
是B
的友元,B
是A
的友元,这并不意味着C
自动成为A
的友元。每一个友元关系需要显式声明。
- 友元关系是不可传递的。即使
-
友元关系不能继承:
- 友元关系不会继承。如果一个类
A
声明了B
为友元类,那么子类B
的所有派生类并不会自动成为A
的友元类。友元关系仅对直接声明它们的类有效。
- 友元关系不会继承。如果一个类
三 内部类:
定义:
内部类是定义在另一个类的内部的类。它可以访问外部类的所有成员,包括私有成员。
特点:
- 内部类可以定义在外部类的
public
、protected
、private
区域。 - 内部类可以直接访问外部类的
static
成员,不需要外部类的对象或类名。 - 内部类的存在对外部类的大小没有任何影响
代码演示:
#include <iostream>
using namespace std;
class Product {
private:
static int discount; // 静态成员变量,用于记录折扣
int price; // 非静态成员变量,记录价格
public:
class Details {
public:
void show(const Product& p) {
cout << "Discount: " << discount << "%" << endl; // 访问静态成员变量
cout << "Price: $" << p.price << endl; // 访问非静态成员变量
}
};
// 构造函数
Product(int p) : price(p) {}
};
// 在类外定义并初始化静态成员变量
int Product::discount = 10;
int main() {
Product::Details d; // 创建嵌套类 Details 的对象
Product p(100); // 创建 Product 类的对象,价格为 100
d.show(p); // 调用 Details 类的成员函数,显示 Product 的信息
return 0;
}
四 匿名对象:
定义:
匿名对象在C++中是指那些在创建时没有被赋予一个变量名的对象。它们的主要特点是生命周期非常短暂,只在创建它们的那条语句中存在,随后就会被销毁。匿名对象的使用场景通常是为了临时操作,比如传递对象作为函数参数或者调用成员函数。
代码演示:
#include <iostream>
using namespace std;
class B
{
public:
B(int b = 0)
: _b(b)
{
cout << "B(int b)" << endl;
}
~B()
{
cout << "~B()" << endl;
}
void display() const
{
cout << "Value: " << _b << endl;
}
private:
int _b;
};
int main()
{
B(5).display(); // 创建一个匿名对象并调用其成员函数
return 0;
}
让我们来主句分析:
-
B(5)
:- 这行代码创建了一个
B
类型的匿名对象。匿名对象意味着这个对象没有名字,也不会被存储在任何变量中。 - 传递参数
5
给构造函数B(int b)
,因此_b
被初始化为5
。 - 构造函数
B(int b)
被调用,输出 "B(int b)"。
- 这行代码创建了一个
-
.display()
:- 匿名对象创建后,立即调用其成员函数
display()
。 display()
函数输出成员变量_b
的值,即 "Value: 5"。
- 匿名对象创建后,立即调用其成员函数
-
对象销毁:
- 由于匿名对象的生命周期仅限于该语句,在调用
display()
函数后,对象立即被销毁。 - 析构函数
~B()
被调用,输出 "~B()"。
- 由于匿名对象的生命周期仅限于该语句,在调用