c++学习笔记(7) 面向对象思想
面向对象思想:
1.string类:
C字符串:将字符串看作以‘/0’结尾的字符数组
string类: 处理字符串
2. 使用string类对象:
// 字符串初始化 string s1 = "Welcome to c++"; string s2("welcome to c++"); //构造方法,更高效
字符串追加函数 append()
字符串赋值函数assign()
#include <iostream> #include <string> #include <iomanip> using namespace std; int main(int argc, char *argv[]) { // append()函数 string s1("Welcome"); // 使用string类的构造方法初始化一个字符串 s1.append(" to c++"); // 直接追加 cout <<"s1 is: " << s1 << endl; string s2("Welcome"); s2.append(" to C and c++", 5); // 将" to c and c++"的前五个字符追加到s2后面 cout << "s2 is: " << s2 << endl; string s3("Welcome"); s3.append(3, 'G'); // 将字符'G'赋值为”GGG“追加到s3的后面 cout << "s3 is: " << s3 << endl; // assign函数 string s4("Welcome"); s4.assign("Dollars"); // 给s4重新赋值 cout << "s4 is: " << s4 << endl; string s5("Welcome"); s5.assign(5, 'F'); // 将”FFFFF“赋值给s5 cout << "s5 is: " << s5 << endl; }
结果:
3. 函数
at(index) 返回索引值处的字符
clear() 清空一个字符串
bool empty()
#include <iostream> #include <string> #include <iomanip> using namespace std; int main(int argc, char *argv[]) { string s1("Welcome"); // 使用string类的构造方法初始化一个字符串 cout << s1.at(3) << endl; cout << s1.erase(2, 3); // 从s1[2]处擦除3个字符 welcome-->weme s1.clear(); cout << s1.empty() << endl; return 0; }
函数
length() 长度
size() 大小
capacity() 存储空间
c_str() 返回一个C字符串
compare() 返回值-1,1,0
substr() : substr(index, n)-->从index起始的n个字符 substr(index) 返回从index起始到末尾的字符串
find() 字符串搜索函数:
find(ch): 返回ch第一次出现的位置
find(sunstr) 子串出现的位置
find(ch, index) 返回从index位置起,ch出现的位置
find(substr, index)
insert(index, s) index位置, s子串
insert(index, n, ch) index位置, n个字符
replace()
5. 数字,字符串 相互转化
1. atoi(), atof(), 将字符串转化为 int 和 float
2. itoa(int n, char [], 2/8/10/16) 将数字转化为字符串
3. <sstream>头文件
stringstream类,提供的接口可以使我们像处理输入输出流一样来处理字符串
code:
#include <iostream> #include <string> #include <iomanip> #include <sstream> // 将数字转化为字符串 using namespace std; int main(int argc, char *argv[]) { stringstream ss; // stringstream类,提供的接口可以使我们像处理输入输出流一样;来处理字符串 ss << 3.1245; string s1 = ss.str(); cout << s1 << endl; cout << s1.erase(2, 2) << endl; // 3.1245-->3.45 ss << 98.45667; string s2 = ss.str(); cout << s2.append("Welcome") << endl; // 98.45667Welcome return 0; }
结果:
6. 字符串分割:
使用stringstream类来完成
#include <iostream> #include <string> #include <iomanip> #include <sstream> // 将数字转化为字符串 using namespace std; int main(int argc, char *argv[]) { string text("Programing is very fun"); // 将每一个单词提取出来 stringstream ss(text); // stringstream类,提供的接口可以使我们像处理输入输出流一样;来处理字符串 cout << "The word in text are: " << endl; string word; while(!ss.eof()) { ss >> word; cout << word << endl; } return 0; }
结果:
7.字符串替换的实现:
将字符串s中的oldSubStr替换为newStr
代码:
#include <iostream> #include <string> #include <iomanip> #include <sstream> // 将数字转化为字符串 using namespace std; bool replaceString(string&, string&, string&); int main(int argc, char *argv[]) { string ss, old_string, new_string; cin >> ss >> old_string >> new_string; bool isReplaced = replaceString(ss, old_string, new_string); if(isReplaced) { cout << ss << endl; } else { cout << "No match"; } return 0; } bool replaceString(string& s, string& oldSubStr, string& newSubStr) { bool isreplaced = false; int current_position = 0; while(current_position<s.length()) { int position = s.find(oldSubStr, current_position); if(position==string::npos) { return isreplaced; } else { s.replace(position, oldSubStr.length(), newSubStr); // 从current_position开始,替换的子串长度,新的子串 current_position = position + newSubStr.length(); // 更新current_position isreplaced = true; } } return isreplaced; }
对象作为函数的参数:
值传递引用传递都是允许的:
对象参数采用值传递,实际上是将对象的内容复制给函数参数
以引用传递的方式:函数的参数实际上是需要传递的对象的一个别名
推荐使用引用传递,因为值传递需要额外的时间和空间
创建对象的回数组:
Circle circleArray[10];
circleArray是一个对象数组,会调用无参构造函数初始化
对象数组例子:
circle.h
// 关于类的定义 #ifndef CIRCLE_H #define CIRCLE_H class Circle { private: double radius; public: // 定义数据域 //double radius; // 构建函数 Circle(); // 构建函数 Circle(double); // 定义函数 double getArea(); // define accessor double getRadius(); // define mutator void setRadius(double); } ; #endif
circle.cpp
// 类的实现 #include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h" Circle::Circle() { radius = 1.0; } Circle::Circle(double new_radius) { radius = new_radius; } double Circle::getArea() { return 3.14*radius*radius; } double Circle::getRadius() { return radius; } void Circle::setRadius(double new_radius) { radius = new_radius; }
main.cpp
#include <iostream> #include <iomanip> #include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h" #include "E:\back_up\code\c_plus_code\chapter10\external_file\loan.h" using namespace std; const int SIZE = 10; double sumCircle(Circle [], int); void printCircle(Circle [], int); int main(int argc, char *argv[]) { Circle circle_array[SIZE]; for(int i=0; i<SIZE; i++) { circle_array[i].setRadius(i+5); } printCircle(circle_array, SIZE); return 0; } double sumCircle(Circle circleArray[], int size) { double sumArea = 0; for(int i=0; i<size; i++) { sumArea += circleArray[i].getArea(); } return sumArea; } void printCircle(Circle circleArray[], int size) { cout << setw(25) << left << "Radius" << setw(8) << "Area" << endl; for(int i=0; i<size; i++) { cout << setw(25) << left << circleArray[i].getRadius() << setw(8) << circleArray[i].getArea() << endl; } cout << "-----------------------------------------"; cout << "The total area of circles is " << sumCircle(circleArray, size) << endl; }
8.实例成员和静态成员
概念: 实例变量和静态变量的区别:
实例变量: 在类的不同对象中是相互独立,互不影响的, 如Circle类中的radius
静态变量(类变量):在类的不同对象中是共享的,如在circle中添加静态变量numberOfObjects表示实例化的对象的个数 // 初始化
实例函数:
静态函数:
修饰符static
区别: 在类中,实例函数,实例变量从属于对象,只有创建对象后,才能通过特定的对象进行访问。
静态函数和静态变量可以通过任意的类对象来访问,也可以直接通过类名访问
注意与匿名类的区别 cout << Circle().radius() cout << Circle(5).radius()这是匿名类
cout << Circle::number_of_object 以及Circle::getObjectNumber()是通过类名直接调用
例子程序: 注意程序中静态变量和静态函数的使用
circle.h
// 关于类的定义 #ifndef CIRCLE_H #define CIRCLE_H class Circle { private: double radius; static int number_of_obj; // 静态变量 类变量 public: // 定义数据域 //double radius; // 构建函数 Circle(); // 构建函数 Circle(double); // 定义函数 double getArea(); // define accessor double getRadius(); // define mutator void setRadius(double); // 静态函数 static int getObjectNumber(); } ; #endif
circle.cpp
// 类的实现 #include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h" int Circle::number_of_obj = 0; // 注意初始化的位置在这里 静态变量 Circle::Circle() { radius = 1.0; number_of_obj++; // 实例化对象时 ++ } Circle::Circle(double new_radius) { radius = new_radius; number_of_obj++; // ++ } double Circle::getArea() { return 3.14*radius*radius; } double Circle::getRadius() { return radius; } void Circle::setRadius(double new_radius) { radius = new_radius; } int Circle::getObjectNumber() { return number_of_obj; }
main.cpp
#include <iostream> #include <iomanip> #include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h" #include "E:\back_up\code\c_plus_code\chapter10\external_file\loan.h" using namespace std; int main(int argc, char *argv[]) { cout << "Created object number is " << Circle::getObjectNumber() << endl; Circle circle1; cout << "circle1 radius is " << circle1.getRadius() << endl; cout << "circle1 areais " << circle1.getArea() << endl; Circle circle2(5); cout << "circle2 radius is " << circle2.getRadius() << endl; cout << "circle2 areais " << circle2.getArea() << endl; cout << "Created object number is " << Circle::getObjectNumber() << endl; cout << "Created object number is " << circle1.getObjectNumber() << endl; cout << "Created object number is " << circle2.getObjectNumber() << endl; circle1.setRadius(10); cout << "circle1 radius is " << circle1.getRadius() << endl; cout << "circle1 areais " << circle1.getArea() << endl; cout << "Created object number is " << Circle::getObjectNumber() << endl; return 0; }
结果:
建议使用类名访问静态函数和静态变量
只读成员函数
在成员函数后面加关键字const,这样相当于告诉编译器该成员函数不会改变数据域
只有实例才能被定义为只读函数
一般访问器函数被定义只读函数
9.从对象的角度考虑
BMI指数获取
重点: 类的定义,实现(具体)
定义实例变量,实例函数,静态变量,静态函数
定义只读函数
调用
code:
bmi.h文件:
#ifndef BMI_H #define BMI_H #include <string> using namespace std; class BMI { private: string user_name; int user_age; double user_weight; double user_height; static int current_user_num; // 静态变量 public: // constructor function BMI(); BMI(string& new_name, int new_age, double new_weight, double new_height); // define accessor 只读函数 string getName() const; int getAge() const; double getWeight() const; double getHeight() const; // define mutator void setName(string& new_new_name); void setAge(int new_new_age); void setHeight(double new_new_height); void setWeight(double new_new_weight); // function general double getBMI() const; string getStatus() const; static int getCurrentUserNum(); // 只有实例方法才能被定义为只读函数 }; #endif
bmi.cpp文件
#include "C:\Users\28491\Desktop\code\hello\external_file\bmi.h" #include <string> using namespace std; int BMI::current_user_num = 0; BMI::BMI() { user_name = "None"; user_age = 0; user_height = 0.0; user_weight = 0.0; current_user_num++; } BMI::BMI(string& new_name, int new_age, double new_weight, double new_height) { user_name = new_name; user_age = new_age; user_weight = new_weight; user_height = new_height; current_user_num++; } // define accessor string BMI::getName() const { return user_name; } int BMI::getAge() const { return user_age; } double BMI::getWeight() const { return user_weight; } double BMI::getHeight() const { return user_height; } // define mutator void BMI::setName(string& new_new_name) { user_name = new_new_name; } void BMI::setAge(int new_new_age) { user_age = new_new_age; } void BMI::setWeight(double new_new_weight) { user_weight = new_new_weight; } void BMI::setHeight(double new_new_height) { user_height = new_new_height; } double BMI::getBMI() const { const double KILOGRAM_PER_POUND = 0.45359237; const double METERS_PER_INCH = 0.0254; double bmi = user_weight * KILOGRAM_PER_POUND / ((user_height * METERS_PER_INCH) * (user_height * METERS_PER_INCH)); return bmi; } string BMI::getStatus() const { double bmi = getBMI(); if(bmi<18.5) return "Under_weight"; else if(bmi<25) return "Normal"; else if(bmi<30) return "Overweight"; else return "Obesity"; } int BMI::getCurrentUserNum() { return current_user_num; }
main.cpp
#include <iostream> #include <ctime> #include <cmath> #include <string> #include "C:\Users\28491\Desktop\code\hello\external_file\bmi.h" using namespace std; int main(int argc, char *argv[]) { string myname("zhangjun"); string hisname("wangwang"); BMI bmi_1(myname, 23, 120, 170); cout << bmi_1.getName() << " is " << bmi_1.getAge() << " years old " << " and height is " << bmi_1.getHeight() << " and weight is " << bmi_1.getWeight() << endl; cout << bmi_1.getName() << " BMI is " << bmi_1.getBMI() << " and status is " << bmi_1.getStatus() << endl; cout << "Current user number is " << BMI::getCurrentUserNum() << endl; BMI bmi_2; bmi_2.setName(hisname); bmi_2.setAge(28); bmi_2.setHeight(180); bmi_2.setWeight(100); cout << bmi_2.getName() << " is " << bmi_2.getAge() << " years old " << " and height is " << bmi_2.getHeight() << " and weight is " << bmi_2.getWeight() << endl; cout << bmi_2.getName() << " BMI is " << bmi_2.getBMI() << " and status is " << bmi_2.getStatus() << endl;; cout << "Current user number is " << BMI::getCurrentUserNum() << endl; //cout << "Bmi_1 name is " << bmi_1.getName() << endl; //cout << "Bmi_1 age is " << bmi_1.getAge() << endl; //cout << "Bmi_1 weight is " << bmi_1.getWeight() << endl; //cout << "Bmi_1 height is " << bmi_1.getHeight() << endl; //cout << "Current user is " << BMI::getCurrentUserNum() << endl; return 0; }
对象的合成:一个对对象可以包含另一个对象
实例研究: stack of integers类
栈(stack): 是一个 “后进先出” 的数据结构
应用: 编译器用栈处理函数的调用,用一个栈保存被调用函数的参数和局部变量。当一个函数调用另一个函数时,新函数的参数和局部变量被压入栈中。当一个函数完成工作,返回调用者时,它占用的空间将从栈中释放掉。
stackofintegers.h
#ifndef STACK_H #define STACK_H class StackOfIntegers { private: int size; // 栈的大小 int element[100]; public: StackOfIntegers(); // 无参数构造函数 bool isEmpty() const; // 只读函数 int peek(); // 返回栈的第一个值 void push(int val); //入栈 int pop(); // 出栈 int getSize() const; // 返回栈的大小 }; #endif
stackofintegers..cpp
#include "C:\Users\28491\Desktop\code\hello\external_file\stackofintegers.h" StackOfIntegers::StackOfIntegers() { size = 0; } bool StackOfIntegers::isEmpty() const { return size == 0; } int StackOfIntegers::peek() { return element[size-1]; } void StackOfIntegers::push(int val) // pop and push 函数的实现 { element[size++] = val; } int StackOfIntegers::pop() // 不是只读函数,对private做出了修改 { return element[--size]; } int StackOfIntegers::getSize() const { return size; }
main.cpp
#include <iostream> #include <ctime> #include <cmath> #include <string> #include "C:\Users\28491\Desktop\code\hello\external_file\stackofintegers.h" using namespace std; int main(int argc, char *argv[]) { StackOfIntegers stack; for(int i=0; i<15; i++) { stack.push(i); if(i==8) { cout << "The first element in stack is " << stack.peek() << endl; } } cout << "Stack Size is " << stack.getSize() << endl; cout << "Pop a number " << stack.pop() << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)