
指针需要先分配内存,否则会指向不确定的位置,可能会引发段错误
因此不要直接定义指针,而是应该定义变量来分配内存。

运算符重载和函数重载类似,不同点在于运算符重载使用 operator 关键字
如:
bool operator==(const Person& other)const {
return name == other.name && age == other.age;
}
通常在类中进行运算符重载。
函数指针是指向函数的指针,允许我们通过指针调用函数。函数指针的类型必须与它指向的函数的签名一致,包括返回类型和参数类型。
// 声明一个指向返回 int 类型、接受两个 int 参数的函数的指针
int(*funcPtr)(int,int);
// 定义一个函数
int add(int a,int b) {
return a + b;
}
int main() {
funcPtr = add; // 将函数地址赋给函数指针
int result = funcPtr(3,4); // 通过指针调用函数
std::cout << "Result: " << result << std::endl; // 输出:7
}
回调函数是一种特殊用途的函数指针,通常被作为参数传递给另一个函数以供调用。回调函数通常用于异步处理或在不确定的情况下调用某个特定的处理逻辑(如事件处理)。
// 定义回调函数类型
typedef void(*Callback)(int);
// 实现一个回调函数
void myCallback(int val) {
std::cout << "Callback called with value: " << val << std::endl;
}
// 接受回调函数的函数
void process(Callback callback,int value) {
// 调用回调函数
callback(value);
}
int main() {
// 将回调函数传递给另一个函数
process(myCallback,10); // 输出:Callback called with value:10
}
指针函数是一个返回指针的函数,和前面提到的函数指针不同。指针函数用于返回一个指针,但自身并不是函数指针。它在函数签名中带有指针符号(*)。
// 返回 int 类型指针的函数
int* getPointer(int& a) {
return &a; // 返回变量 a 的地址
}
int main() {
int x = 10;
int* ptr = getPointer(x); // ptr 指向 x
std::cout << *ptr << std::endl; // 输出:10
}
回调函数依赖于函数指针的机制,而指针函数与这两者无直接关系。
static 变量只会在第一次调用函数时初始化,并在程序的生命周期内保持其值,即使函数执行结束它的值也不会丢失。static 成员变量属于整个类而不是类的某个对象,因此所有对象共享同一个 static 成员变量。static 函数其作用域也仅限于定义它的文件,其他文件无法访问它。用于定义常量, 或限制变量、指针、函数的修改权限,以提高代码的安全性和可读性
将变量声明为 const 表示它的值一旦初始化后就不能再更改。
在使用指针时,const 关键字可以指定指针指向的内容不可更改,或者指针本身不可更改。
const int* p = &x;const int* p = &x; // p 指向的内容不可更改,但 p 可指向其他地址
*p = 20; // 错误,不能修改指向内容
int y = 30;
p = &y; // 可以更改 p 的指向
int* const p = &x;int x = 10;
int* const p = &x; // p 是常量指针,不可指向其他地址
*p = 20; // 可以修改 p 指向的内容
p = &y; // 错误,不能更改 p 的指向
const int* const p = &x;const int* const p = &x; // p 和 p 指向的内容都不可更改
*p = 20; // 错误,不能修改指向内容
p = &y; // 错误,不能更改 p 的指向
const 成员函数,表示该函数不能修改对象的任何成员变量(除了 mutable 修饰的变量)。const 成员函数只能调用其他 const 成员函数。const 不用于修饰普通函数,对于普通函数往往用来修饰其返回值和传入参数
class MyClass {
public:
int getValue()const { return value; } // const 成员函数
void setValue(int val) { value = val; } // 非 const 成员函数
private:
int value = 0;
};
int main() {
MyClass obj;
obj.getValue(); // 可以调用 const 成员函数
obj.setValue(10); // 可以调用非 const 成员函数
}
const 对象只能调用其 const 成员函数,因为 const 对象不允许被修改。
const MyClass obj;
obj.getValue(); // 可以调用 const 成员函数
obj.setValue(10); // 错误,不能调用非 const 成员函数
const将函数参数声明为 const 可以防止在函数内部修改传入的值,常用于传入大对象时避免副本带来的开销。
const 引用传递,可以防止函数内部修改参数,且避免了值传递带来的性能损耗。void printValue(const MyClass& obj) {
std::cout << obj.getValue() << std::endl;
}
const 指针参数可以防止函数内部修改指针指向的内容。void processValue(const int* p) {
// *p = 10; // 错误,不能修改指向内容
}
const 的函数const 可以防止对返回值进行修改,通常用于返回类成员的引用时。const int& getValue()const {
return value;
}
const 与 mutable 结合mutable 关键字可以让某些成员变量在 const 成员函数中被修改。class MyClass {
public:
void increment()const { count++; } // 可以在 const 成员函数中修改 count
private:
mutable int count = 0; // mutable 允许在 const 函数中修改
};
mutable关键字让成员变量在const成员函数中可以被修改,适用于缓存、计数等场景。mutable仅用于类的非静态成员变量,且仅在const成员函数中生效。
单例模式确保一个类只有一个实例,并提供全局访问点
单例模式通常用在数据库连接池、线程池等应用场景
关键之处:
class single{
public:
static single& getsingle(){
static single instance;
return instance;
}
private:
Single(){}
线程安全
class Singleton {
private:
Singleton() {} // 私有构造函数
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton instance; // 静态实例
public:
static Singleton& getInstance() {
return instance;
}
};
需要时才创建,线程不安全,可能多个线程同时创建单例
class Singleton {
private:
static Singleton* instance;
Singleton() {}
public:
static Singleton* getInstance() {
if(instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
通过互斥锁来保证线程安全
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
public:
static Singleton* getInstance() {
std::lock_guard<std::mutex> lock(mtx);
if(instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
每次调用 getInstance 都要加锁,影响性能。
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx;
Singleton() {}
public:
static Singleton* getInstance() {
if(instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx);
if(instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
};
// 静态成员初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
在多线程环境下效率较高,先检查指针,再加锁,再次检查,确保只创建一次实例。
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
引用本质上是别名,在内存中与被引用变量占用同一存储单元
引用不能为空,必须在定义时初始化
引用一旦初始化不能再改变指向,但能改变变量值
对引用 sizeof,返回的是被引用变量的大小

友元函数是 C++ 中的一种特殊函数,它能够访问类的私有(**private**)和受保护(**protected**)成员,而普通函数不能直接访问这些成员。友元函数并不是类的成员函数,但它与类关系密切,通过 **friend**** 关键字声明。**
就像朋友一样
当两个类需要紧密协作时,友元函数允许其中一个类直接操作另一个类的内部数据。跨类访问私有成员
如:
class Box {
private:
double width;
public:
Box(double w) :width(w) {}
// 声明友元函数
friend void printWidth(const Box& b);
};
// 定义友元函数
void printWidth(const Box& b) {
cout << "Width: " << b.width << endl;
}
int main() {
Box b(10.5);
printWidth(b); // 直接访问私有成员 width
return 0;
}
//输出
Width:10.5
**跨类访问私有成员: **当两个类需要紧密协作时,友元函数可以实现跨类访问,避免暴露内部实现。
class Square;
class Rectangle {
private:
double length,width;
public:
Rectangle(double l,double w) :length(l),width(w) {}
// 声明友元函数
friend double areaDifference(const Rectangle&,const Square&);
};
class Square {
private:
double side;
public:
Square(double s) :side(s) {}
// 声明友元函数
friend double areaDifference(const Rectangle&,const Square&);
};
// 友元函数定义
double areaDifference(const Rectangle& rect,const Square& sq) {
double rectArea = rect.length * rect.width;
double squareArea = sq.side * sq.side;
return rectArea - squareArea;
}
int main() {
Rectangle rect(4.0,5.0);
Square sq(3.0);
cout << "Area difference: " << areaDifference(rect,sq) << endl;
return 0;
}
//输出
// Area difference:11
友元函数可以让非成员函数直接访问类的私有和受保护成员,用于:
<< 和 >>)。public)。| 特性 | 友元函数 | 成员函数 |
|---|---|---|
| 定义位置 | 类外定义,但需在类内声明 | 类内声明和定义(也可类外定义) |
| 访问权限 | 可以访问私有和受保护成员 | 可以访问私有和受保护成员 |
| 调用方式 | 像普通函数一样调用 | 必须通过对象或指针调用 |
| 是否属于类 | 不属于类 | 属于类 |
| 特性 | 友元函数 | 友元类 |
|---|---|---|
| 定义 | 一个函数 | 一个类 |
| 访问范围 | 访问类的私有和受保护成员 | 访问类的所有私有和受保护成员 |
| 使用场景 | 用于具体的函数协作 | 用于复杂类间协作 |
类的继承方式:
**public**** 继承**:父类的 public 成员在子类中保持为 public,protected 成员在子类中保持为 protected。**protected**** 继承**:父类的 public 和 protected 成员在子类中都变为 protected。**private**** 继承**:父类的 public 和 protected 成员在子类中都变为 private。继承的父类成员:
**private**):
public 或 protected)间接访问。**protected**):
**public**):
private 成员的目的是隐藏实现细节,确保它只能被类自身访问。子类不能直接访问私有成员的原因是为了更好地封装和安全性。
构造函数、析构函数、友元函数、静态数据成员、静态成员函数都不能被继承!
protected 成员在类的外部不可访问。即不能通过对象.成员的方式访问protected 成员会根据继承方式(public、protected、private)调整其在派生类中的访问权限。C++ 的多态分为编译时多态(函数重载、运算符重载)和运行时多态(虚函数实现的动态多态)。
运行时多态的特点:
virtual)实现。什么是动态绑定:
基类指针指向子类对象时,如
Animal* ani = new Duck();调用的成员方法在运行时动态绑定到子类中的重写方法。若不使用 virtual 实现多态(虚函数),而是在子类中定义相同的方法,则不能动态绑定。
class Animal {
public:
void jiao(){ cout << "动物叫" << endl;}
};
class Duck: public Animal {
public:
void jiao() { cout << "嘎嘎嘎" << endl;}
};
int main(){
Duck duck;
Animal* ani = new Duck();
duck.jiao();
ani->jiao();
}
//输出:
嘎嘎嘎
动物叫
class Animal {
public:
virtual void jiao(){ cout << "动物叫" << endl;}
};
class Duck: public Animal {
public:
void jiao()override { cout << "嘎嘎嘎" << endl;}
};
int main(){
Duck duck;
Animal* ani = new Duck();
duck.jiao();
ani->jiao();
}
//输出:
嘎嘎嘎
嘎嘎嘎