C++ 类和对象 友元 内部类 this指针 默认成员函数 初始化列表……
1. 类和对象的基本概念
- 类:用户自定义的数据类型,包含数据成员(属性)和成员函数(方法)。
- 对象:类的实例,占用内存空间,具有类中定义的属性和方法。
示例:
class Dog { // 定义类
public:
std::string name; // 属性
int age;
void bark() { // 方法
std::cout << name << " says: Woof!" << std::endl;
}
};
int main() {
Dog myDog; // 创建对象
myDog.name = "Buddy";
myDog.age = 3;
myDog.bark(); // 输出:Buddy says: Woof!
return 0;
}
2. 访问限定符
- public:类外可直接访问。
- private:仅类内和友元可访问(默认访问权限)。
- protected:类内、派生类和友元可访问。
示例:
class Student {
private:
int score; // 私有成员,外部不可访问
public:
std::string name;
void setScore(int s) { score = s; } // 通过公有方法修改私有成员
};
int main() {
Student stu;
stu.name = "Alice";
stu.setScore(90);
// stu.score = 85; // 错误:score是private成员
return 0;
}
3. 面向对象的三大特征
3.1 封装
将数据和操作数据的方法绑定,隐藏实现细节。
3.2 继承
允许新类继承现有类的成员,实现代码复用。
class Animal {
public:
void eat() { std::cout << "Eating..." << std::endl; }
};
class Cat : public Animal { // 继承Animal
public:
void meow() { std::cout << "Meow!" << std::endl; }
};
int main() {
Cat cat;
cat.eat(); // 继承自Animal
cat.meow(); // 自身方法
return 0;
}
3.3 多态
通过虚函数实现运行时绑定(需继承和虚函数支持)。
class Shape {
public:
virtual void draw() { std::cout << "Drawing a shape" << std::endl; } // 虚函数
};
class Circle : public Shape {
public:
void draw() override { std::cout << "Drawing a circle" << std::endl; } // 重写虚函数
};
int main() {
Shape* shape = new Circle();
shape->draw(); // 输出:Drawing a circle(多态)
delete shape;
return 0;
}
4. 对象存储方式
- 栈内存:对象在栈上分配,生命周期随作用域结束自动销毁。
- 堆内存:对象通过
new
在堆上分配,需手动delete
释放。 - 对象的存储方式设计:对象存储方式的设计:只保存成员变量,成员函数放在公共的代码段里,编译链接是就会根据函数名去公共代码区找到函数的地址,然后Call函数地址
5. this指针
指向当前对象的指针,用于区分成员变量与局部变量。
示例:
class Box {
private:
int width;
public:
void setWidth(int width) {
this->width = width; // this访问成员变量
}
};
6. 构造函数与析构函数
6.1 构造函数
- 初始化对象,与类同名,无返回类型。
- 默认构造函数:无参或所有参数有默认值。
- 带参数的构造函数:初始化对象时传入参数。
6.2 析构函数
- 对象销毁时自动调用,用于释放资源。
- 名称:
~ClassName()
,无参数。
示例:
class Book {
public:
std::string title;
Book() { title = "Unknown"; } // 默认构造函数
Book(const std::string& t) : title(t) {} // 带参数的构造函数
~Book() { std::cout << title << " destroyed" << std::endl; } // 析构函数
};
int main() {
Book book1; // 调用默认构造
Book book2("C++ Primer"); // 调用带参构造
return 0; // 析构函数自动调用
}
7. 拷贝构造函数
- 用于通过同类型对象初始化新对象。
- 默认浅拷贝,需自定义深拷贝(如涉及指针)。
示例:
class Array {
private:
int* data;
int size;
public:
Array(int s) : size(s) { data = new int[s]; } // 构造函数
Array(const Array& other) : size(other.size) { // 拷贝构造(深拷贝)
data = new int[size];
memcpy(data, other.data, size * sizeof(int));
}
~Array() { delete[] data; } // 析构函数释放内存
};
8. 运算符重载
允许自定义运算符对类对象的操作。
示例(重载+
运算符):
class Vector {
public:
int x, y;
Vector(int x, int y) : x(x), y(y) {}
Vector operator+(const Vector& other) { // 重载+
return Vector(x + other.x, y + other.y);
}
};
int main() {
Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2; // 调用重载的+
return 0;
}
9. 默认成员函数
编译器自动生成的函数(若未显式定义):
- 默认构造函数(若无其他构造函数)。
- 默认析构函数。
- 默认拷贝构造函数(浅拷贝)。
- 默认赋值运算符(浅拷贝)。
- 移动构造运算符。
- 移动赋值运算符。
10. const成员
- const成员函数:不能修改成员变量。
- const对象:只能调用const成员函数。
示例:
class Counter {
private:
mutable int count; // mutable成员可在const函数中修改
public:
Counter() : count(0) {}
void increment() { count++; }
int getCount() const { return count; } // const成员函数
};
int main() {
const Counter c;
// c.increment(); // 错误:const对象不能调用非const函数
int cnt = c.getCount(); // 允许调用const函数
return 0;
}
11. static成员
- static成员变量:所有对象共享,类外初始化。
- static成员函数:只能访问static成员,无
this
指针。
示例:
class Player {
public:
static int playerCount; // 静态成员变量声明
Player() { playerCount++; }
static void showCount() { std::cout << playerCount << std::endl; } // 静态函数
};
int Player::playerCount = 0; // 类外初始化
int main() {
Player p1, p2;
Player::showCount(); // 输出:2
return 0;
}
12. 友元
- 友元函数/类:允许访问类的私有成员。
- 破坏封装性,慎用。
示例:
class Box {
private:
int width;
friend void printWidth(Box box); // 友元函数声明
};
void printWidth(Box box) {
std::cout << box.width << std::endl; // 访问私有成员
}
int main() {
Box b;
printWidth(b);
return 0;
}
13. 初始化列表
在构造函数中初始化成员变量(效率更高,必须用于const成员)。
示例:
class Student {
private:
const int id; // const成员必须用初始化列表
std::string name;
public:
Student(int i, const std::string& n) : id(i), name(n) {}
};
14. 匿名对象
没有名字的临时对象,生命周期仅限当前行。
示例:
class Logger {
public:
Logger() { std::cout << "Logger created" << std::endl; }
~Logger() { std::cout << "Logger destroyed" << std::endl; }
};
int main() {
Logger(); // 创建匿名对象,立即析构
return 0;
}
// 输出:
// Logger created
// Logger destroyed
15. 内部类
定义在类内部的类,可访问外部类的静态成员。
示例:
class Outer {
private:
static int value; // 外部类静态成员
public:
class Inner { // 内部类
public:
void print() {
std::cout << "Outer::value = " << value << std::endl; // 访问外部类静态成员
}
};
};
int Outer::value = 100;
int main() {
Outer::Inner inner;
inner.print(); // 输出:Outer::value = 100
return 0;
}
16. new/malloc 与 delete/free 对比
特性 | new/delete | malloc/free |
---|---|---|
类型安全 | 是(自动计算大小) | 否(需手动计算大小) |
调用构造/析构 | 是 | 否 |
内存来源 | 自由存储区(可能是堆) | 堆 |
失败处理 | 抛出bad_alloc 异常 | 返回NULL |
重载 | 可重载operator new/delete | 不可重载 |
示例:
int main() {
int* p1 = new int(10); // 调用构造函数
delete p1; // 调用析构函数
int* p2 = (int*)malloc(sizeof(int)); // 无构造
free(p2); // 无析构
// 混用会导致未定义行为
// int* p3 = new int;
// free(p3); // 错误!
return 0;
}
16. 思维导图
(网课版本可通过右键图片在心标签页中打开然后方大网页观看,也可保存到本地查看)