1.1 thish指针
上两篇文章每个类成员函数都只涉及到一个对象,即调用它的对象,但有时候需要涉及到两个对象,this指针就发挥重要作用。
例如:为了让程序查看一系列股票,找到价格最高的那一支,可以定义一个成员函数,让它查看两个Stock对象,并返回股价较高的那个对象的引用。
1.1.1 Q1:如何将两个要比较的对象提供给成员函数?
假设将该方法命名为topval( ),则函数调用stock1.topval( )将访问stock1对象的数据,而stock2.topval( )将访问stock2对象的数据。如果希望该方法读两个对象进行比较,则必须将第二个对象作为参数传递给他,效率第一原则,可以按“引用”来传递参数,即topval( )方法使用一个类型为 const Stock&的参数。
1.1.2 Q2: 如何将方法的答案传回给调用程序?
让方法返回一个引用,该引用指向股价总值较高的对象。
Const Stock & topval( const Stock & s ) const;
分析上述函数:
- 该函数隐式地访问了一个对象,而显式地访问另外一个对象,并返回其中一个对象的引用;
- 括号中的const表明,该函数不会修改被显式地访问的对象;
- 括号后的const表明,该函数不会修改被隐式地访问的对象;
- 该函数返回了两个const对象之一的引用,因此返回类型也应为const引用。
如果用关系操作符 > 来比较这两个对象,将更为清晰:
const Stock & Stock::topval (const Stock & s) const{
if (s.total_val > total_val)
return s;
else
return ???}
s.total_val 是作为参数传递的对象的总值(显式), total_val是用来调用该方法的对象的总值(隐式);如果s.total_val大于total_val,则函数返回s,否则将返回调用该方法的对象。
1.1.3 Q:这个对象究竟怎么表现?
如果调用stock1.topval(stock2),则s是stock2的引用(即别名),但stock1没有别名。C++提供解决这个问题的方法,使用this特殊指针。
This指针指向用来调用成员函数的对象。函数调用stock1.topval(stock2)将this设置为stock1对象的地址,stock2.topval(stock1),将this设置为stock2对象的地址.所有类方法都将this指针设置为调用它的对象的地址,通过指针来访问结构成员,也适用于类成员this->total_val.
1.2 this指针详解
每个成员函数(包括构造函数和析构函数)都有一个this指针,this指针指向调用对象,如果方法要引用整个调用对象,则可以用*this;当要返回的并不是this,因为this是对象的地址,而是对象本身,即*this(将接触引用操作符*用于指针,将得到指针指向的值。图为this调用两个对象:
1.3 程序实现
1.3.1 stock20.h文件:
#ifndef __STOCK20_H__
#define __STOCK20_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 = "Error", long n= 0, double pr =0.0); //默认构造函数
Stock(const std::string &co , long n, double pr);//获取哪家公司的股票,买多少支股票,每支股票价格
~Stock();
void buy(long num , double price);//购买股票的数量和价格
void sell(long num , double price);//出售股票的数量和价格
void update(double price);//更新股票的价格
void show() const;//显示股票当前信息
//函数返回值是const 类型的引用,函数名为topval,不允许通过this指针隐式访问对象
const Stock &topval(const Stock &s) const;
};
#endif
1.3.2 stock20.cpp文件
#include <iostream>
#include "stock20.h"
Stock::Stock() //默认构造函数只能有1个
{
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
//编写函数具体实现
Stock::Stock(const std::string &co, long n, double pr) //默认构造函数
{
company = co;//在公共定义的函数里访问私有的成员变量
if(n < 0)
{ //不能购买负的股票
std::cout << "Number of shares can't be negative; "<< company << "shares set to be 0."<<std::endl;
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
Stock::~Stock()
{
std::cout << "Bye" << company <<"\n";
}
void Stock::buy( long num , double price )
{
if(num < 0)
{ //不能购买负的股票
std::cout << "Number of shares can't be negative,tuansaction is aborted "<<std::endl;
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
using std::cout;
if(num < 0)
{ //不能卖负的股票
std::cout << "Number of shares can't be negative,tuansaction is aborted "<<std::endl;
}
else if (num >shares) //卖出股票的数目不能超出当前手中的数目
{
cout << "You can't sell more than you have! Transanction is aborted"<<std::endl;
}
else
{
shares -= num;
share_val = price; //更新当前股票价格
set_tot();//计算当前资产
}
}
void Stock::update(double price) //更新当前股票的价格
{
share_val = price;
set_tot();//更新当前的总资产
}
void Stock::show() const
{
std::cout << "Company: " << company << std::endl;
std::cout << "Share: " << shares << std::endl;
std::cout << "Share price "<< share_val << std::endl;
std::cout << "Total worth: "<< total_val << std::endl;
}
const Stock &Stock::topval(const Stock &s) const //不希望this指针改变对象的值,返回隐式或显式对象
{
if(s.total_val > total_val) //total_val == this ->total_val
return s;
else
return *this; //取值运算符,返回this指针指向的对象的内容
}
1.3.3 usestock20.cpp文件
#include <iostream>
#include "stock20.h"
int main (void)
{
using std::cout;
Stock stock1("Nanosmart", 12, 20.0); //隐式调用构造函数
stock1.show();
Stock stock2 = Stock("Boffo objects" , 2, 2.0);//显式调用构造函数
stock2.show();//运用类的对象调用构造函数
//比较两支股票谁总额比较大
Stock top = stock1.topval(stock2); //利用stock1类的对象来访问topval,与stock2进行比较
cout << "\nNow show the top val:\n";
top.show();
return 0;
}
1.3.4 程序运行结果
2.1 对象数组
用户通常要创建同一个类的多个对象,可以创建独立对象变量,但创建对象数组将更为合适。
1.Stock mystuff[ 4 ],其中每个元素都是Stock的对象
mystuff[ 0 ].update();
mystuff[ 3 ].show();
2.用构造函数初始化数组元素
Const int STK = 4;
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.0),
Stock("Boffo Objects", 200, 2.0),
Stock("Mono", 130, 3.25),
Stock("Fleep", 60, 6.5)
};
使用标准格式对数组进行初始化:用括号括齐,以逗号分隔的值列表,每次构造函数调用表示一个值,如果类包含多个构造函数,则可以对不同的元素使用不同的构造函数:
const int STK = 10 ;
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.0),
Stock( ),
Stock("Boffo Objects", 200, 2.0),
上述代码使用Stock(const char * co, int n, double pr)来初始化stock[0]和stock[2],使用Stock()构造函数初始化stock[1 ],由于该声明只初始化了数组的部分元素,因此余下的元素将使用默认构造函数进行初始化。
初始化对象数组的方案:
- 使用默认构造函数创建数组元素
- 花括号中的构造函数将创建临时对象
- 临时对象的内容赋值到相应的元素中
因此,要创建类对象数组,则这个类必须要有默认构造函数
2.2 代码实现(更改的主函数文件,其余函数文件同上)
#include <iostream>
#include "stock20.h"
const int STKS = 4;
int main(void)
{
Stock stocks[STKS] = {
Stock("NanoSmart", 12, 20.0),
Stock("Boffo Objects", 200, 2.0),
Stock("Mono", 130, 3.25),
Stock("Fleep", 60, 6.5)
};
std::cout << "Stock holding:\n\n";
int st;
for(st = 0; st < STKS; st++)
stocks[st].show(); //访问每一个类的对象
const Stock *top = &stocks[0]; //取出对象的指针
for(st = 1; st< STKS; st++)
//top指针指向的对象和topval函数对象进行比较
//要保证类型匹配,处理完毕后,取出最大股票类的对象地址传递给类的指针
top =&top->topval(stocks[st]);
std::cout << "\nMost valuable holding:\n";
top->show(); //指针对象访问成员函数
return 0;
}
2.3 运行结果