1.运算符
1.1 单目运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<iostream> using namespace std; class MyNumber{ private: int value; public: MyNumber(int v):value(v){}; MyNumber& operator++()//重载前置递增运算符++,前置递增运算符返回引用(允许修改原始对象并立即访问修改后的对象) { value++; return *this; } MyNumber operator++(int)//重载后置递增运算符++,返回原始对象的副本,int 参数只是为了区分前置和后置递增运算符 { MyNumber temp(*this); value++; return temp; } void display() { cout<<"value:"<<value<<endl; } }; int main() { MyNumber num(5); MyNumber num2=num++; num2.display(); num.display(); ++num; num.display(); return 0; }
out: value:5 value:6 value:7
|
注:如果只想执行递增运算,可使用++ object,也可使用 object ++,但应选择前者,这样避免创建一个未被使用的临时拷贝。
1.2 转换运算符
转换运算符 const char* :对象的内容转换成 cout 能够接受的类型(const char*)
ostringstream:属于 <sstream>
头文件,并提供了将各种数据类型(如整数、浮点数、字符串等)转换为字符串的能力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream> #include <sstream> // 用于 ostringstream #include <string> #include<cstdio> using namespace std;
// 自定义日期类 class Date { private: int day, month, year; string dateInString;
public: // 构造函数,用于初始化日期对象 Date(int inMonth, int inDay, int inYear) : month(inMonth), day(inDay), year(inYear) {};
// 类型转换运算符,将日期对象转换为 const char* 类型的指针 operator const char*() { ostringstream formattedDate; // 辅助构建字符串 formattedDate << month << " / " << day << " / " << year; dateInString = formattedDate.str(); return dateInString.c_str();//dateInString.c_str(),返回一个 const char* 类型的指针 } };
int main() { // 创建日期对象,表示圣诞节的日期 Date Holiday(12, 25, 2016);
// 直接输出日期对象,由于重载了类型转换运算符,它将自动转换为字符串并输出 cout << "Holiday is on: " << Holiday << endl; // 下面是其他使用示例的注释部分 // string strHoliday(Holiday); // 可行! // strHoliday = Date(11, 11, 2016); // 也是可行的!
return 0; }
|
1.3 双目运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream>
class Complex { private: double real; double imaginary;
public: Complex(double r, double i) : real(r), imaginary(i) {}
// 重载加法运算符 + Complex operator+(const Complex& other) { double newReal = real + other.real; double newImaginary = imaginary + other.imaginary; return Complex(newReal, newImaginary); }
// 打印复数的成员函数 void display() { std::cout << real << " + " << imaginary << "i" << std::endl; } };
int main() { Complex num1(3.0, 4.0); Complex num2(1.0, 2.0);
Complex sum = num1 + num2; // 使用重载的 + 运算符
std::cout << "Sum: "; sum.display();
return 0; }
out: Sum: 4 + 6i
|
1.4 重载下标运算符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> #include <stdexcept> using namespace std; class MyArray { private: int arr[10]; // 假设数组大小为 10
public: // 重载下标运算符 [] int& operator[](int index) { if (index < 0 || index >= 10) { throw std::out_of_range("Index out of range"); } return arr[index]; } };
int main() { MyArray myArray;
// 初始化数组元素 for (int i = 0; i < 10; ++i) { myArray[i] = i; }
// 使用下标运算符 [] 访问数组元素并输出 for (int i = 0; i < 10; ++i) { cout << "myArray[" << i << "] = " << myArray[i] << endl; } return 0; }
out: myArray[0] = 0 myArray[1] = 1 myArray[2] = 2 myArray[3] = 3 myArray[4] = 4 myArray[5] = 5 myArray[6] = 6 myArray[7] = 7 myArray[8] = 8 myArray[9] = 9
|
1.5 函数运算符 operator()
operator()让对象像函数,被称为函数运算符。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <iostream> #include <string> using namespace std;
// 定义一个类 Display class Display { public: // 重载函数调用运算符 (),用于输出传入的字符串 void operator () (string input) const {//const: 这个关键字表示该运算符函数是一个常量成员函数,告诉编译器在函数内部不会修改对象的状态。 cout << input << endl; } };
int main () { // 创建 Display 类的对象 displayFuncObj Display displayFuncObj; // 使用函数调用运算符 () 调用 displayFuncObj,传入字符串参数 displayFuncObj("Display this string! "); return 0; }
out: Display this string!
|
2.类型转换运算符
2.1 static_cast
static_cast:显式地将一种数据类型转换为另一种数据类型,在执行转换时会进行编译时类型检查,以确保类型转换是合法的。
static_cast的语法如下:
new_type static_cast<new_type>(expression)
其中:
new_type
表示要进行的目标类型(目标数据类型)。
expression
是要转换的表达式或值。
主要用途:
基本数据类型之间的转换(主要用途):如整数到浮点数,浮点数到整数,以及其他基本数据类型之间的转换。
指针类型之间的转换:在执行时不会进行运行时检查,因此应该谨慎使用
类之间的转换:可以用于父类和子类之间的转换,但它不执行运行时检查,因此应谨慎使用。
枚举类型的转换:可以用于枚举类型之间的转换。
1 2 3 4 5
| class Parent { /* ... */ }; class Child : public Parent { /* ... */ };
Parent* parentPtr = new Child(); Child* childPtr = static_cast<Child*>(parentPtr); // 将父类指针转换为子类指针
|
2.2 dynamic_cast
dynamic_cast:主要用于在继承关系中进行安全的运行时类型识别和类型转换。
dynamic_cast 的语法如下:
dynamic_cast<new_type>(expression)
其中:
new_type
表示要进行的目标类型(目标数据类型)。
expression
是要转换的指针或引用。
dynamic_cast的主要用途如下:
- 用于多态类型的安全类型转换:
dynamic_cast
主要用于处理多态类的情况
*注:dynamic_cast会在运行时检查是否可以进行安全的类型转换。如果转换不合法(例如,试图将基类指针转换为未与之相关的派生类指针),则会返回空指针(对于指针)或引发 std::bad_cast异常(对于引用)。*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> #include <typeinfo>
class Animal { public: virtual void speak() { std::cout << "Animal speaks" << std::endl; } };
class Dog : public Animal { public: void speak() override { std::cout << "Dog barks" << std::endl; } };
int main() { Animal* animal = new Dog();
// 使用 dynamic_cast 将基类指针转换为派生类指针 Dog* dog = dynamic_cast<Dog*>(animal);
if (dog) { // 转换成功,现在可以安全地调用 Dog 类的函数 dog->speak(); } else { // 转换失败 std::cout << "Failed to cast to Dog" << std::endl; }
delete animal;
return 0; }
out: Dog barks
|
2.3 const_cast
const_cast:用于在一定情况下去除对象的常量性,可以添加或移除对象的 const
限定符,从而改变对象的常量属性。
const_cast:的语法如下:
const_cast<new_type>(expression)
其中:
new_type
表示要进行的目标类型(目标数据类型)。
expression
是要转换的指针、引用或对象。
注:
1.const_cast:主要用于去除对象的 const
限定符,使其变为非常量对象,从而允许对其进行修改。
2.const_cast:不会修改对象的实际值,只是修改了对象的类型属性。
主要用途:用于解决某些兼容性问题,例如调用老式库函数,这些函数不将参数标记为常量,但实际上不会修改它们。
1 2 3 4 5 6 7 8 9 10
| #include <iostream> #include <typeinfo>
int main() { const int value = 42; int* nonConstPtr = const_cast<int*>(&value); *nonConstPtr = 100; // 合法,修改了原本是常量的对象 return 0; }
|
3.map和unordered_map(hash_map)的区别
map:基于红黑树(二叉搜索树)实现,元素按照key的顺序进行排序存储(有序,增删改查log(n)的复杂度)
unordered_map:基于哈希表实现,根据键的哈希值分布(增删改查log(1)的复杂度)
注:如果要对元素的key值排序使用map
4.emplace_back和push_back的区别
emplace_back和push_back的用法:向vector末尾添加元素
push_back:
- 在vector外构建对象
使用move或拷贝构造添加到vector的末尾
在vector外构建的对象析构了
emplace_back:
- 直接在vector内构造对象(接受构造该对象所需的参数,并在vector内部直接调用该对象的构造函数)
用法:
1 2 3
| std::vector<Person> vec; vec.push_back(Person("Alice", 30)); vec.emplace_back("Bob", 25);
|
5.stringstream
头文件:#include <sstream>
作用1:格式化字符串(将各种类型的数据传入字符串中)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| struct SStud { int nNumb; char sName[20]; float fMath; }; int main() { stringstream ostr; SStud d = { 1008,"学生1",89.5 }; ostr << "学号:" << d.nNumb << "\t" << d.sName << "\t" << d.fMath << endl; string str = ostr.str(); cout << str << endl; return 0; }
|
作用2:截断字符串(按空格截断)
1 2 3 4 5
| string s1, s2, s3; ostr >> s1 >> s2 >> s3; cout << s1 << endl; cout << s2 << endl; cout << s3 << endl;
|
作用3:以指定字符delim
分割字符串
1 2 3 4 5 6 7 8 9 10 11 12
| vector<string> split(const string& s, char delim) { vector<string> result; stringstream ss(s); string item; while (getline(ss, item, delim)) { cout << item << endl; result.emplace_back(item); } return result; }
|