C++学习笔记
一:输入输出
输出格式
cout<<x<<endl;
输出多个数据
cout<<x<<y<<endl;
输入格式
cin>>x;
输入多个数据
cin>>x>>y;
作用域符号
“::”
二:类
类的定义模板
class 类名(首字母一般大写)
{public:共有数据;protected:保护的数据;private:私有的数据;
};
实例化对象
在这里需要注意一点:类用于指定对象的形式 。
实例化对象有两种方式:(实例化和初始化不一样,实例化是创造对象,初始化是对象已经存在,对对象进行操作)
1.从堆中实例化对象
自己创建,自己释放 new开辟内存,delet释放内存
class Point {
public:int x, y;Point(int x, int y) : x(x), y(y) {}
};
// 实例化对象
Point* p = new Point(10, 20); // 堆上分配内存
// 释放内存(避免内存泄漏)
delete p;
2.从栈中实例化对象
由系统自动分配内存并释放
class Point {
private:int x, y;
public:Point() : x(0), y(0) {} //构造函数
};
// 实例化对象
Point p; // 调用默认构造函数
三:构造函数和析构函数
构造函数
作用:创建对象时自动调用,用于初始化对象的成员变量、分配资源。
构造函数的函数名必须和类名完全一致。且可以重载
构造函数:后面的是成员以,区分。
#include <iostream>
using namespace std;
class Array {
private:int* data; // 动态数组指针int size; // 数组大小
public:// 1. 默认构造函数(无参数)Array() : data(nullptr), size(0) {cout << "默认构造函数调用:空数组初始化" << endl;}
// 2. 带参数构造函数(按需初始化)Array(int len) : size(len) {data = new int[size]; // 分配动态内存cout << "带参数构造函数调用:创建大小为 " << size << " 的数组" << endl;// 初始化数组元素(示例:全部设为 0)for (int i = 0; i < size; i++) {data[i] = 0;}}
// 3. 拷贝构造函数(用已有对象初始化新对象)// 参数必须是「const 类对象引用」,避免递归调用Array(const Array& other) {size = other.size;// 深拷贝:为新对象单独分配内存data = new int[size];for (int i = 0; i < size; i++) {data[i] = other.data[i];}cout << "拷贝构造函数调用:复制数组(深拷贝)" << endl;}
// 4. 移动构造函数(C++11+,高效转移资源)// 参数是「类对象的右值引用」(形如 &&)Array(Array&& other) noexcept {// 直接接管资源,避免拷贝size = other.size;data = other.data;// 让原对象失去资源(避免析构时重复释放)other.data = nullptr;other.size = 0;cout << "移动构造函数调用:转移数组资源(浅拷贝+接管)" << endl;}
// 5. 委托构造函数(C++11+,复用构造逻辑)// 调用已有的带参数构造函数Array() : Array(0) {} // 等价于默认构造函数逻辑
};
析构函数
作用:对象声明周期结束时自动调用,用于释放资源,避免内存泄漏。
析构函数~ + 类名
析构函数不能重载
class Array {// 析构函数~Array() {// 释放动态分配的内存if (data != nullptr) {delete[] data;data = nullptr; // 置空避免野指针cout << "析构函数调用:释放大小为 " << size << " 的数组" << endl;}}
};
四:this指针
this指针用于指向类自身成员的数据。即:当前对象的引用
特点:
1.this只能在成员函数中使用,即该成员属于这一类,才可以使用
2.全局函数和静态函数不能使用,因为他们不属于任何一个类。
五:继承
可以用一个基类来定义一个派生类。派生类继承了基类的已有成员。
// 基类
class Animal {
protected:std::string name;
public:Animal(const std::string& n) : name(n) {}void eat() { std::cout << name << " is eating." << std::endl; }
};
// 派生类(继承自 Animal)
class Dog : public Animal {
public:Dog(const std::string& n) : Animal(n) {} // 调用基类构造函数void bark() { std::cout << name << " says woof!" << std::endl; }
};
// 使用示例
Dog dog("Buddy");
Dog.eat(); // 继承自 Animal
Dog.bark(); // Dog 特有的方法
继承方式有三种:共有继承,保护继承,私有继承
继承方式 | 基类的 public 成员 | 基类的 protected 成员 | 基类的 private 成员 |
---|---|---|---|
public | 仍为 public | 仍为 protected | 不可访问 |
protected | 变为 protected | 仍为 protected | 不可访问 |
private | 变为 private | 变为 private | 不可访问 |
六:重载
重载主要分为两种,一种是函数重载,一种是运算符重载。
1.函数重载
同名函数:在同一作用域内,函数名相同但参数列表不同(参数类型、数量或顺序)。
返回值不参与重载:仅返回值不同的函数无法重载。
// 同一类中的函数重载
class Calculator {
public:int add(int a, int b) { return a + b; } // 版本1:两个intdouble add(double a, double b) { return a + b; } // 版本2:两个doubleint add(int a, int b, int c) { return a + b + c; } // 版本3:三个int
};
// 使用示例
Calculator calc;
calc.add(1, 2); // 调用版本1
calc.add(1.5, 2.5); // 调用版本2
calc.add(1, 2, 3); // 调用版本3
2.运算符重载
通过定义特殊的成员函数或非成员函数实现运算符重载
基本格式:返回类型 operator + 运算符(参数列表) { /* 实现 */ }
class Dog{public:int weight;Dog operator+(const Dog &d) {Dog dog;dog.weight = this->weight + d.weight;return dog;}
};
int main(){Dog dog1;Dog dog2;Dog dog3;dog1.weight = 10;dog2.weight = 20;dog3 = dog1 + dog2;cout<<"第三只狗的体重是: "<<dog3.weight<<endl;return 0;
}
七:多态
允许不同的对象通过相同的接口进行调用,从而实现“一种接口,多种实现方式”。主要分为静态多态和动态多态。
主要是结合函数重载实现。
1.静态多态
编在编译时确定具体的调用函数。
class Calculator {
public:int add(int a, int b) { return a + b; } // 整数加法double add(double a, double b) { return a + b; } // 浮点数加法
};
// 使用示例
Calculator calc;
calc.add(1, 2); // 编译时确定调用 int 版本
calc.add(1.5, 2.5); // 编译时确定调用 double 版本
2.动态多态
通过虚函数和继承实现,在运行时根据对象的实际类型确定调用的函数。
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;}
};
class Square : public Shape {
public:void draw() override { // 重写基类虚函数std::cout << "Drawing a square." << std::endl;}
};
// 使用示例
void renderShape(Shape* shape) {shape->draw(); // 运行时根据实际对象类型决定调用哪个版本
}
int main() {Circle circle;Square square;
renderShape(&circle); // 输出:"Drawing a circle."renderShape(&square); // 输出:"Drawing a square."return 0;
}
虚函数(virtual
): 在基类中用 virtual
声明的函数,派生类可重写(override)它。
重写(override
): 派生类中与基类虚函数签名相同的函数会自动成为虚函数,用 override
显式标记