C++学习笔记(6)

面向对象编程:
1.对象和类

(1)声明类: 类定义了对象的属性行为

        一个对象的状态: 用数据域以及他们的当前值来表示。

        一个对象的行为,由一组函数确定。

        所以在c++类中,用变量定义数据域,用函数来定义行为

 (2)定义类和创建对象:
       定义一个圆的类:

#include <iostream>

using namespace std;

class Circle
{
	public:
	double radius;
	
	// constructor 
	Circle()
	{
		radius = 1.0;
	}
	// 构造方法 
	Circle(double new_radius)
	{
		radius = new_radius;
	}
	// 函数 
	double getArea()
	{
		return 3.14 * radius * radius;
	}
	
};     // 这里要写分号 

int main(int argc, char *argv[])
{
        Circle circle1;
	Circle circle2(12.5);
	Circle circle3(123);
	
	cout << "radius of circle 1 is " << circle1.radius << endl;
	cout << "Area of circle 3 is " << circle3.getArea() << endl;
   
	return 0;
}

public关键字:表示所有的数据域,构造函数和普通成员函数都可以通过类对象来访问。如果不用关键字public,那么这些成员的可见性缺省为private

了解UML图(Unified Modelling Language)统一建模语言描述

简单程序:定义一个电视TV的类,包括频道切换,开关机,音量调节

#include <iostream>

using namespace std;

class TV
{
    public:
    int channel;
    int volume_level;
    bool on;
    
    //定义构造方法 
    TV()
    {
       channel = 1;
	   volume_level = 40;
	   on = false;	
    }
    
    void turnOn()
    {
    	on = true;
    }
    
    void turnOff()
    {
    	on = false;
    }
    
    void setChannel(int new_channel)
    {
    	if(on && new_channel >=1 && new_channel<=120)
    	{
	    	channel = new_channel;
	    }
    }
    
    void setVolume(int volume)
    {
    	if(on && volume>=0 && volume<=100)
    	{
	    	volume_level = volume;
	    }
    }
    
    void channelUp()
    {
    	if(on && channel<120)
    	    channel++;
    }
    
    void channelDowm()
    {
    	if(on && channel>0)
    	    channel--;
    }
    
    void volumeUp()
    {
    	if(on && volume_level<100)
    	   volume_level++;
    }
    
    void volumeDown()
    {
    	if(on && volume_level>0)
    	   volume_level--;
    }
    
};
int main(int argc, char *argv[])
{
    TV tv1;
    cout << "The state of tv is " << tv1.on << endl;
    cout << "The channel is " << tv1.channel << endl;
    cout << "The volume is " << tv1.volume_level << endl;
    
    tv1.turnOn();
    tv1.setChannel(56);
    tv1.setVolume(60);
    cout << "The state of tv is " << tv1.on << endl;
    cout << "The channel is " << tv1.channel << endl;
    cout << "The volume is " << tv1.volume_level << endl;
    
    tv1.channelUp();
    tv1.volumeDown();
    cout << "The state of tv is " << tv1.on << endl;
    cout << "The channel is " << tv1.channel << endl;
    cout << "The volume is " << tv1.volume_level << endl;
    
    return 0;
}

2.构造函数

  构造函数可以理解为一种特殊的函数,与普通的函数相比,主要不同点有:

  1.构造函数的名字必须与类的名字相同

  2.构造函数没有返回类型  返回void也不可以

  3.创建对象时,构造函数被调用, 他的作用就是初始化对象

构造函数也可以重载(可以同名,但函数签名不同),构造函数用来初始化数据域。

注: 类中的变量作为类的新成员,在声明时不能进行初始化。比如Circle类里面的radius,在声明不能初始化,只能在构造方法中为其赋值。

3.创建及使用对象

对象创建后,可以通过.运算(即对象成员访问运算符)来访问对象的数据以及调用对象的函数

尽量将类名的每个单词首字母大写

“=”可以进行两个对象之间内容的复制,但他们仍然是两个不同的对象

@@,一个对象包含的数据存储在内存里,但是函数并不需要存储,因为函数是这个类所有对象共享的,编译器仅仅创建一份拷贝就可以了。例如对于circle1, circle2,他们的大小都是一个double类型所占的字节的大小。

@@有时创建一个对象,但只需要使用一次,这时无需为对象命名,创建为匿名对象即可

3.类定义和类实现的分离

   分离类定义和类实现有利于类的维护。

   使用类的程序称为客户程序。

  ::称为二元作用域解析运算符,指明类成员的作用范围。

   分离的好处:

  1.可以实现隐藏。在不改变类的定义的前提下,可以自由修改类的实现

  2.作为软件供应商,只要提供类定义的文件和类实现的目标代码,从而隐藏了类实现的源代码,保护软件上的知识产产权

  类定义放在h文件中,类实现在.cpp文件中

 .h文件中类的定义

// 关于类的定义
class Circle 
{
   public:
   // 定义数据域 
   double radius;
   // 构建函数 
   Circle();
   // 构建函数
   Circle(double);
   // 定义函数
   double getArea(); 
   	
} 

 

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

在main.cpp中调用:

#include <iostream>
#include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h"

using namespace std;

int main(int argc, char *argv[])
{
	Circle c1;
	Circle c2(5);
	
	cout << "The radius of c1 is " << c1.radius << endl;
	cout << "The area of c1 is " << c1.getArea() << endl;
	
	cout << "The radius of c2 is " << c2.radius << endl;
	cout << "The area of c2 is " << c2.getArea() << endl;
	return 0;
}

注: include 应该包含circle.h的完整路径,否则会报错

4.避免多次包含

Head.h文件

#include circle.h

Test.cpp文件:

#include circle.h

#include head.h

     在上面的代码中,circle.h被重复包含,编译器会报错

     如何解决在一个程序中多次包含相同的头文件。如果多次包含,C++编译器会报错,因为预处理器会把#include后的内容直接插入到他们被包含的位置,如果重复包含,就相当于重复插入了相同的内容,就会出现类有多个定义的报错。

包含保护: 原语句 #ifndef和#define可以避免头文件多次被包含,所以在头文件中应该包含。

// 关于类的定义
#ifndef CIRCLE_H
#define CIRCLE_H 
class Circle 
{
   public:
   // 定义数据域 
   double radius;
   // 构建函数 
   Circle();
   // 构建函数
   Circle(double);
   // 定义函数
   double getArea(); 
   	
} ;
#endif


 

 先测试CIRCLE_H是否已经定义,如果没有,则定义,并且把头文件的其他部分也包含进来,否则跳过、

5. 数据域封装

 数据域私有可以保护数据,使类便于维护。

例如,对于类Circle,要防止客户程序直接修改radius的值,以防止客户程序直接修改类的属性,因此,使用关键字private,将数据域设为私有,这就是数据域封装。

一个私有的程序,无法通过直接引用类对象来访问它。 如果需要访问,需改,需要定义一个get()函数和一个set()函数,即访问器(accessor)和更改器(mutator)

Circle类:

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>=0) ? new_radius : 0;  //语法糖
}

客户端程序:

#include <iostream>
#include "E:\back_up\code\c_plus_code\chapter10\external_file\circle.h"

using namespace std;

int main(int argc, char *argv[])
{
	//Circle c1;
	Circle c2(5);
	
	cout << "The radius of c2 is " << c2.getRadius() << endl;
	cout << "The area of c2 is " << c2.getArea() << endl;
	
	c2.setRadius(10.5);
	cout << "The radius of c2 is " << c2.getRadius() << endl;
	cout << "The area of c2 is " << c2.getArea() << endl;
	return 0;
}

6.变量作用域

全局变量

局部变量

局部静态变量

在类中,数据域被定义为便变量的形式,可以被所有成员函数访问

在类中,如果一个局部变量和一个数据域有相同的名字,数据域将被覆盖,局部变量的优先级是最高的

7.类的抽象和封装

银行获取贷款的例子:

Loan:

数据域: 利率, 贷款额度, 贷款年限 (用private实现类的封装)

构造方法: Loan()以及Loan(int, double , double)

函数:

year(access,  mutator),  

loan_amount(access,  mutator)

interest_rate(access,  mutator)

getMonthlyPayment()

getTotalPayment()

代码:

Loan.h文件:

// loan的定义 
#ifndef LOAN_H
#define LOAN_H

class Loan
{
	public:
	// 构造方法
	Loan();
	Loan(int year, double loan_amount, double year_interest_rate);
	 
	int getYear();  // accessor for year
	void setYear(int);  // mutator for year
	
	double getYearInterestRate();  // accessor for interest rate
	void setYearInterestRate(double);  //  mutator for interest rate
	
	double getLoanAmount();  // access for LoanAmount
	void setLoanAmount(double);   //mutator for
	
	double getMonthPayment();
	double getTotalPayment();
	
	private:
	int years;
	double loan_amounmt;
	double year_interest_rate;
	//double month_payment;
	//double total_payment;
};

#endif 

Loan.cpp文件:
 

// 类的实现 
#include "E:\back_up\code\c_plus_code\chapter10\external_file\loan.h"
#include <cmath>

Loan::Loan()
{
	years = 5;
	loan_amounmt = 100000;
	year_interest_rate = 4;
}

Loan::Loan(int year, double amounmt, double rate)   // 在类的实现中,参数的名字不能与变量的名字相同 
{
    years = year;
	loan_amounmt = amounmt;
	year_interest_rate = rate;	
}

int Loan::getYear()
{
	return years;
}

void Loan::setYear(int year)
{
	years = year;
}

double Loan::getYearInterestRate()
{
	return year_interest_rate;
}

void Loan::setYearInterestRate(double rate)
{
	year_interest_rate = rate;
}

double Loan::getLoanAmount()
{
	return loan_amounmt;
}

void Loan::setLoanAmount(double amounmt)
{
	loan_amounmt = amounmt;
}

double Loan::getMonthPayment()
{
	double month_interest_rate = year_interest_rate / 1200;
	return loan_amounmt * month_interest_rate / (1 - pow(1 / (1+month_interest_rate), years * 12)); 
}

double Loan::getTotalPayment()
{
    return getMonthPayment() * 12 * years;	
}

注:在类的实现中函数参数的命名与类中的数据域命名应该不一样,否则会有错误(程序不报错,但会出现错误的结果)

用户程序:

#include <iostream>
#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[])
{
    Loan loan_1;
	cout << "The year is " << loan_1.getYear() << endl;
	cout << "loan amount is " << loan_1.getLoanAmount() << endl; 
	cout << "loan rate is " << loan_1.getYearInterestRate() << endl;
	cout << "month payment is " << loan_1.getMonthPayment() << endl;
	cout << "total payment is " << loan_1.getTotalPayment() << endl;   

	
	loan_1.setYear(10);
	loan_1.setYearInterestRate(8.5);
	loan_1.setLoanAmount(80000);
	cout << "-----------------------------" << endl;
	cout << "The year is " << loan_1.getYear() << endl;
	cout << "loan amount is " << loan_1.getLoanAmount() << endl; 
	cout << "loan rate is " << loan_1.getYearInterestRate() << endl;
	cout << "month payment is " << loan_1.getMonthPayment() << endl;
	cout << "total payment is " << loan_1.getTotalPayment() << endl; 
	
	Loan loan_2(15, 30000, 6.4);
	cout << "-----------------------------" << endl;
	cout << "The year is " << loan_2.getYear() << endl;
	cout << "loan amount is " << loan_2.getLoanAmount() << endl; 
	cout << "loan rate is " << loan_2.getYearInterestRate() << endl;
	cout << "month payment is " << loan_2.getMonthPayment() << endl;
	cout << "total payment is " << loan_2.getTotalPayment() << endl; 
    
   	return 0;
	
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-09-29 21:40  Alpha205  阅读(74)  评论(0编辑  收藏  举报