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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-10-13 10:44  Alpha205  阅读(131)  评论(0编辑  收藏  举报