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;
}