这部分是c++升级c的主要内容,也是c++的精髓部分,c是面向过程的,而C++是面向对象的。面向对象编程(OOP)的最重要特性有:
*抽象
*封装和数据隐藏
*多态
*继承
*代码的可重用性
1.抽象和类:
C++中的类,是一种将抽象将抽象转换为用户定义类型的C++工具(其他面向对象语言也类似,如java),它将数据表示和操纵数据的方法组合成一个整
洁的包。
定义类的规范有两个部分:类声明和类方法定义。
类声明:以数据成员的方式描述数据部分,以成员函数(也成为方法)的方式描述公有接口。
类方法定义:描述如何实现类成员函数。
简单地说就是,类声明提供了类的蓝图,而类的方法定义则提供了实现细节。
对类成员的控制访问:由于隐藏数据时oop的主要目标之一,所以数据项通常放在私有部分(private),组成类接口的成员函数放在公有部分,否则就无
法从程序中调用这些函数,一般使用私有成员函数来处理不属于公共接口的实现细节。有时候不必使用private关键字,因为C++中,private是类对象默认
访问控制。
现在学了类了,对类和结构的区别有了更进一步的了解:实际上类是对结构的扩展,他们有很多的相同特性,唯一区别是,结构的默认访问控制室public,
类是private的。注意:结构体也可以定义方法:例如如下:
public struct Person
{
string name;
double height;
double weight;
public void OverWeight()
{
.....
}
}
成员函数的定义:与常规函数定义非常相似,但是有两个特色的特征:
(1)定义成员函数是,使用作用域解析操作符(::)来标识函数所属的类
(2)类方法可以访问类的private组件
代码示例:
#include<iostream>
#include<cstring>
using namespace std;
//类声明
class Stock
{
private:
char company[30];//公司名称
int shares;//所持股票的数量
double share_val;//每股的价格
double total_val;//股票总值
void SetTol()//这是个内陆函数
{
total_val=shares*share_val;
}
public:
void Acquire(const char *co,int n,double pr);//获得股票
void Buy(int num,double price);//增持股票
void Sell(int num,double price);//卖出股票
void Update(double price);//更新股票价格
void Show();//显示关于所持股票的信息
};
//定义类的成员函数
void Stock::Acquire(const char *co,int n,double pr)
{
strncpy(company,co,29);
company[29]='\0';
if(n<0)
{
cerr <<"股票数量不能为负的!"<<endl;
cerr <<company<<"的股票数量设置为0"<<endl;
shares = 0;
}
else
shares = n;
share_val = pr;
SetTol();
}
void Stock::Buy(int num,double price)
{
if(num<0)
{
cerr<<"增持股票数量不能为负的!"<<endl;
}
else
{
shares +=num;
share_val=price;
SetTol();
}
}
void Stock::Sell(int num,price)
{
if(num<0)
{
cerr<<"卖出股票数量不能为负的!"<<endl;
}
if(num>shares)
{
cerr<<"你卖出的股票数量不能大于你所持有的数量"<<endl;
}
else
{
shares = shares - num;
share_val=price;
SetTol();
}
}
void Stock::Update(double price)
{
share_val=price;
SetTol();
}
void Stock::Show()
{
cout <<"company: "<<company;
cout <<" shares: "<<shares<<endl;
cout <<"share price:$"<<share_val;
cout <<"total Worth:$"<<total_val<<endl;
}
cerr对象:和cout对象一样,也是一个ostream对象,之间的区别在于,操作系统重定向只影响cout,而不影响cerr。cerr对象用于错误信息
内联方法:在类声明中定义的的函数都将自动成为内联函数。因此以上SetTol()函数就是内联函数
注意:调用成员函数时,它将使用被用来调用它的对象的成员数据。所创建的对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个累的 所有对象共享同一组类方法,集每个方法(函数)只有一个副本。
2.类的构造函数和析构函数:
构造函数:是创建对象是自动调用的,但是不能通过对象来调用构造函数。还有就是不能将类成员名称用作构造函数的参数!
析构函数:用构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。对象过期时,程序将自动调用一个特殊的函数来完成清理工作,这个函数就是析构函数
代码示例:
stock.h文件代码:
#include<iostream>
#include<cstring>
using namespace std;
//类声明
class Stock
{
private:
char company[30];//公司名称
int shares;//所持股票的数量
double share_val;//每股的价格
double total_val;//股票总值
void SetTol()//这是个内陆函数
{
total_val=shares*share_val;
}
public:
Stock();
Stock(const char *co,int n,double pr);
~Stock();
void Acquire(const char *co,int n,double pr);//获得股票
void Buy(int num,double price);//增持股票
void Sell(int num,double price);//卖出股票
void Update(double price);//更新股票价格
void Show();//显示关于所持股票的信息
};
stock.cpp文件代码:
#include<iostream>
#include<cstring>
#include"stock.h"
using namespace std;
//类的实现
//定义类的成员函数
Stock::Stock()//默认构造函数
{
cout<<"Default constructor called:"<<endl;
strcpy(company,"noname");
shares=0;
share_val=0.0;
total_val=0.0;
}
Stock::Stock(const char *co ,int n,double pr)//构造函数
{
cout<<"Constructor using:"<<endl;
strncpy(company,co,29);
company[29]='\0';
if(n<0)
{
cerr <<"股票数量不能为负的!"<<endl;
cerr <<company<<"的股票数量设置为0"<<endl;
shares = 0;
}
else
shares = n;
share_val = pr;
SetTol();
}
Stock::~Stock()//析构函数
{
cout<<"bye, "<<company<<"!"<<endl;//输出只是为了了解什么时候析构函数被调用。
}
void Stock::Buy(int num,double price)
{
if(num<0)
{
cerr<<"增持股票数量不能为负的!"<<endl;
}
else
{
shares +=num;
share_val=price;
SetTol();
}
}
void Stock::Show()
{
cout <<"company: "<<company;
cout <<" shares: "<<shares<<endl;
cout <<"share price:$"<<share_val;
cout <<" total Worth:$"<<total_val<<endl;
cout <<endl;
}
main.cpp文件代码:
#include <cstdlib>
#include <iostream>
#include<cstring>
#include"stock.h"
using namespace std;
int main(int argc, char *argv[])
{
cout.setf(ios_base::fixed);//格式化
cout.precision(2);//格式化
cout.setf(ios_base::showpoint);//格式化
cout<<"Using constructor to new objects:"<<endl;
Stock stock1("NanoSmart",12,20.0);
stock1.Show();
Stock stock2=Stock("Boffo Objects",2,2.0);
stock2.Show();
cout<<"Assigning stock1 to stock2:"<<endl;
stock2=stock1;
cout<<"Listing stock1 and stock2:"<<endl;
stock1.Show();
stock2.Show();
cout<<"Using a constructor to reset an object:"<<endl;
stock1=Stock("Nifty Food",10,50.0);
cout<<"Revised stock1:"<<endl;
stock1.Show();
cout<<"Done\n";
return 0;
}
以上三个文件编译连接运行后的结果如下:
想想结果为什么会这样??
const 成员函数:将const放在类函数之后,如 void Show()const,这样定义就是const成员函数,一般情况下,只要类方法不修改对象,则就应该将其声明为const。
构造函数的特例:接受一个参数的构造函数允许使用赋值句法来将对象初始化一个值,如构造函数原型为:Bob(int age);
则可以这样初始化:Bob czm=22;这是第三种初始化对象的方法。
3.this指针:指向用来调用成员函数的对象(this被作为隐藏参数传递给方法)。每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象,this也是一个指针,所以和一般的指针一样,*this指针指向的值。
代码示例:
const Stock& Stock::Topval(const Stock & s) const
{
if (s.total_val>total_val)
return s;
else
return *this;
}
4.对象数组:要创建类对象数组,这个类必须有默认构造函数。因为初始化对象数组时,首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时变量,然后将临时变量的内容复制到相应的元素中。如:Stock stk[4] = {Stock("caizhiming",2,20),Stock("caizhicong"),Stock("caizhiming2",333,34),};
现在对this指针比较了解了,现在深入了解C++的工作方式,比如C++前端cfront将c++程序转换为c程序:处理方法的定义时,只需将下面C++的定义:
void Stock::Show()const
{
cout <<"company: "<<company;
cout <<" shares: "<<shares<<endl;
cout <<"share price:$"<<share_val;
cout <<" total Worth:$"<<total_val<<endl;
}
转换为类C风格的定义:
void Show(const Stock *this)
{
cout <<"company: "<<this->company;
cout <<" shares: "<<this->shares<<"\n";
cout <<"share price:$"<<this->share_val;
cout <<" total Worth:$"<<this->total_val<<"\n";
}
同样的,将top.Show()转换为Show(&top)
5.小结:
面向对象编程强调的是程序如何表示数据。类是用户定义的类型,而对象则是类的实例,即对象是这种类型的变量。如果希望成员函数对多个对象进行操作,则可以将额外的对象作为参数传递给它。如果方法需要显示的引用调用它的对象,则可以使用this指针。