1.1 抽象和类
1,定义:类是一种将抽象转换为用户自定义类型的C++工具,他将数据表示和操纵数据的方法组合成一个整洁的包。
2,类的开发和编写使用该类的程序
C++程序将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源代码文件中。
2.1 类定义
类声明的实例代码:
创建名为stock.h的头文件
//使用infdef来防止同一文件的多重包含
#ifndef STOCK_H
#define STOCK_H
#include<string>
class Stock
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot(){total_val = shares * share_val;}
public:
Stock();
Stock(const std::string &co,long m, double n);
~Stock();
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
代码解释:
1,访问控制
private和public描述了对类成员的访问控制。使用类对象的程序可以直接访问共有部分,但只能通过共有成员函数来访问对象的私有成员。因此,共有成员函数是程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。
注意:数据项通常放在私有部分,描述不属于共有接口实现细节的成员函数也放在私有部分,只有组成类接口的成员函数放在公有部分。
实例中的set_tot()属于私有成员函数。
2,构造函数
定义:对于一个类而言只有对其定义了构造函数其才能想C++中自定义的数据类型一样进行初始化。类构造函数专门用于构造新对象、将值赋值给他的数据成员。
使用:构造函数是一种特殊的成员函数,在创建类对象时被调用;
构造函数的名称和类名相同,但通过函数的重载可以创建多个同名的构造函数,条件是每个函数的参数都不同(实例中便创建了两个构造函数);
构造函数没有声明类型;
需要注意的是,如果程序中没有提供任何构造函数则编译器会为程序定义一个默认构造函数,此时的构造函数是无参数的。
构造函数的参数表示的不是类成员,而是赋给类成员的值。因此参数名不能与类成员相同。
3,析构函数
定义:用构造函数创建对象后,程序负责跟踪该对象,知道其过期为止。对象过期时,程序将自动调用一个特殊的成员函数:析构函数,负责清理工作~Stock();
析构函数也可以没有返回值和声明类型
析构函数没有参数
因为析构函数是程序在对象过期时自动调用的所以通常不在代码中显示的调用析构函数
如果对象是使用new创建的,则其将驻留在栈内存或自由存储区中,当使用delete来释放内存时,其析构函数将自动被调用。
2.2 实现类成员函数
创建名为stock.cpp的实现文件:
<pre name="code" class="cpp">#include<iostream>
#include"stock.h"
Stock::Stock()
{
std::cout << "Default constructor called:\n";
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const std::string &co, long m, double n)
{
std::cout << "Constructor using " << co <<"called\n";
company = co;
if(m < 0)
{
std::cout << "Number of shares can't be negative; "
<< company <<" shares set to 0.\n";
shares = 0;
}else
shares = m;
share_val = n;
set_tot();
}
Stock::~Stock()
{
std::cout << "Bye, "<< company <<" !\n";
}
void Stock::buy(long num, double price)
{
if(num < 0)
{
std::cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else
{
shares+=num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
if(num < 0)
{
std::cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else if(num>shares)
{
std::cout << "You can't sell more than you have! "
<<"Transaction is aborted.\n";
}
else{
shares-=num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
using std::cout;
using std::ios_base;
ios_base::fmtflags orig = cout.setf(ios_base::fixed,ios_base::floatfield);
std::streamsize prec = cout.precision(3);
cout << "company: "<<company
<< " Shares: "<<shares<<'\n';
cout << "shares price: $"<<share_val;
cout.precision(2);
cout<<" Total worth: $ "<<total_val <<'\n';
cout.setf(orig,ios_base::floatfield);
cout.precision(prec);
}
1,首先其需要包含头文件
"stock.h"
2,定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类;
类方法可以访问类的private的组件
注意出构造函数和析构函数外其他函数都应表明返回类型
3,内联方法
当某个函数是在类声明中定义时则这个函数称为内联函数。该例中的Stock::set_tot()便是内联函数,类声明中常将短小的成员函数作为内联函数。
若要在类声明之外定义成员函数,并使其成为内联函数则需要在类实现部分定义函数时使用inline限定符。
2.3 使用类
创建使用文件usestock.cpp
#include <iostream>
#include"stock.h"
int main()
{
{
using namespace std;
cout<<"using constructors to creat new object\n";
Stock stock1("zhai",12,2.0);
stock1.show();
Stock stock2("zhao",15,3.0);
stock2.show();
cout<<"Assigning stock1 to stock2:\n";
stock2=stock1;
cout<<"Listing stock1 and stock2:\n";
stock1.show();
stock2.show();
cout<<"Using a constructor to reset an object\n";
stock1 = Stock("zhaiandzhao",30,8.0);
stock1.show();
cout<<"Done!\n";
}
std::cin.get();
std::cin.get();
return 0;
}
1,使用类中完成了对象的创建、复制等操作。
2,需要注意的是,下面两条语句有根本性的差别:
Stock stock1 = Stock("zhai",12,2.0);
stock1 = Stock("zhaiandzhao",30,8.0);
第一条语句是初始化,他创建有指定值的对象,可能会创建临时对象也可能不会;第二条是赋值语句,像这种在赋值语句中使用构造函数总会导致在复制前创建一个临时对象。
具体表现形式便是,前一个语句的运行结果可能不会出现析构函数中的语句,而后一个语句肯定会运行析构函数。
3,const函数
注意,以后只要类方法不会修改调用对象,就应将其声明为const,实例中的show()函数就是这样的
void stock::show() const