首页 > 其他分享 >The this Pointer (this 指针) and An Array of Objects (对象数组)

The this Pointer (this 指针) and An Array of Objects (对象数组)

时间:2024-06-30 20:30:39浏览次数:3  
标签:std const val object Objects Array total Pointer Stock

The this Pointer [this 指针] and An Array of Objects [对象数组]

1. The this Pointer (this 指针)

class Stock {
private:
	double total_val_;
	...
public:
	double Total() const { return total_val_; }
	...
};

That is, you can use the Total() method to obtain the value, but the class doesn’t provide a method for specifically resetting the value of total_val_.
可以使用方法 Total() 来获得 total_val_ 的值,但这个类没有提供专门用于重新设置 total_val_ 的值的方法。

const Stock & Stock::TopVal(const Stock & stock) const {
	if (stock.total_val_ > total_val_) {
		return stock;  // argument object
	}
	else {
		return *this;  // invoking object
	}
}

The most direct way is to have the method return a reference to the object that has the larger total value.
最直接的方法是让方法返回一个引用,该引用指向 total_val_ 较高的对象。

This function accesses one object implicitly and one object explicitly, and it returns a reference to one of those two objects. The const in parentheses states that the function won’t modify the explicitly accessed object, and the const that follows the parentheses states that the function won’t modify the implicitly accessed object. Because the function returns a reference to one of the two const objects, the return type also has to be a const reference.
该函数隐式地访问一个对象,而显式地访问另一个对象,并返回其中一个对象的引用。括号中的 const 表明,该函数不会修改被显式地访问的对象;而括号后的 const 表明,该函数不会修改被隐式地访问的对象。由于该函数返回了两个 const 对象之一的引用,因此返回类型也应为 const 引用。

top = stock1.TopVal(stock2);
top = stock2.TopVal(stock1);

The first form accesses stock1 implicitly and stock2 explicitly, whereas the second accesses stock1 explicitly and stock2 implicitly. Either way, the method compares the two objects and returns a reference to the one with the higher total value.
第一种格式隐式地访问 stock1,而显式地访问 stock2;第二种格式显式地访问 stock1,而隐式地访问 stock2无论使用哪一种方式,都将对这两个对象进行比较,并返回 total_val_ 较高的那一个对象。

The fact that the return type is a reference means that the returned object is the invoking object itself rather than a copy passed by the return mechanism.
返回类型为引用意味着返回的是调用对象本身,而不是其副本。

在这里插入图片描述

Here stock.total_val_ is the total value for the object passed as an argument, and total_val_ is the total value for the object to which the message is sent. If stock.total_val_ is greater than total_val_, the function returns a reference to stock. Otherwise, it returns a reference to the object used to evoke the method. In OOP talk, that is the object to which the total_val_ message is sent. If you make the call stock1.TopVal(stock2), then stock is a reference for stock2 (that is, an alias for stock2), but there is no alias for stock1.
stock.total_val_ 是作为参数传递的对象的总值,total_val_ 是用来调用该方法的对象的总值。如果 stock.total_val_ 大于 total_val_,则函数将返回指向 stock 的引用;否则,将返回用来调用该方法的对象。在 OOP 中,是 total_val_ 消息要发送给的对象。如果调用 stock1.TopVal(stock2),则 stockstock2 的引用 (即 stock2 的别名),但 stock1 没有别名。

evoke [ɪˈvəʊk]:vt. 唤起,引起 (感情、记忆或形象)

The this pointer points to the object used to invoke a member function. Basically, this is passed as a hidden argument to the method. Thus, the function call stock1.TopVal(stock2) sets this to the address of the stock1 object and makes that pointer available to the TopVal() method. Similarly, the function call stock2.TopVal(stock1) sets this to the address of the stock2 object. In general, all class methods have a this pointer set to the address of the object that invokes the method. Indeed, total_val_ in TopVal() is just shorthand notation for this->total_val_ .
this 指针指向用来调用成员函数的对象,this 被作为隐藏参数传递给方法。这样,函数调用 stock1.TopVal(stock2)this 设置为 stock1 对象的地址,使得这个指针可用于 TopVal() 方法。同样,函数调用 stock2.TopVal(stock1)this 设置为 stock2 对象的地址。一般来说,所有的类方法都将 this 指针设置为调用它的对象的地址。确实,TopVal() 中的 total_val_ 只不过是 this->total_val_ 的简写。

在这里插入图片描述

Each member function, including constructors and destructors, has a this pointer. The special property of the this pointer is that it points to the invoking object. If a method needs to refer to the invoking object as a whole, it can use the expression *this. Using the const qualifier after the function argument parentheses qualifies this as being a pointer to const; in that case, you can’t use this to change the object’s value.
每个成员函数 (包括构造函数和析构函数) 都有一个 this 指针。this 指针指向调用对象。如果方法需要引用整个调用对象,则可以使用表达式 *this在函数的括号后面使用 const 限定符将 this 限定为 const,这样将不能使用 this 来修改对象的值。

What you want to return, however, is not this because this is the address of the object.You want to return the object itself, and that is symbolized by *this. Recall that applying the dereferencing operator * to a pointer yields the value to which the pointer points. Now you can complete the method definition by using *this as an alias for the invoking object.
要返回的并不是 this,因为 this 是对象的地址,而是对象本身,即 *this。将解除引用运算符 * 用于指针,将得到指针指向的值。现在,可以将 *this 作为调用对象的别名来完成前面的方法定义。

  • stock.h
#ifndef STOCK_H_
#define STOCK_H_

#include <string>

// class declaration
class Stock {
private:
	std::string company_;
	int shares_;
	double share_val_;
	double total_val_;

	void SetTot() { total_val_ = shares_ * share_val_; }
public:
	Stock();  // Default constructor
	Stock(const std::string &company, const long num = 0, const double price = 0.0);

	~Stock();

	void Buy(const long num, const double price);
	void Sell(const long num, const double price);
	void Update(const double price);
	void Show()const;

	const Stock &TopVal(const Stock &stock) const;
}; // Note semicolon at the end

#endif

  • stock.cpp
#include <iostream>

#include "stock.h"

// Default constructor
Stock::Stock() {
	std::cout << "Stock::Stock()" << "\n";
	company_ = "default name";
	shares_ = 0;
	share_val_ = 0.0;
	total_val_ = 0.0;
}

Stock::Stock(const std::string &company, const long num, const double price) {
	std::cout << "Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): " << company << "\n";
	company_ = company;
	if (num < 0) {
		std::cout << "Number of shares_ can't be negative; " << company_ << " shares_ set to 0.\n";
		shares_ = 0;
	}
	else {
		shares_ = num;
	}

	share_val_ = price;

	SetTot();
}

// Destructor
Stock::~Stock() {
	std::cout << "Stock::~Stock(): " << company_ << "\n";
}

void Stock::Buy(const long num, const 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;
		SetTot();
	}
}

void Stock::Sell(const long num, const double price) {
	if (num < 0) {
		std::cout << "Number of shares_ sold 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;
		SetTot();
	}
}

void Stock::Update(const double price) {
	share_val_ = price;
	SetTot();
}

void Stock::Show() const {
	// set format to #.###
	std::ios_base::fmtflags original = std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
	std::streamsize precision = std::cout.precision(3);

	std::cout << "Company: " << company_ << "\n  Shares = " << shares_;
	std::cout << "  Share Price = $" << share_val_;

	// set format to #.##
	std::cout.precision(2);
	std::cout << "  Total Worth = $" << total_val_ << '\n';

	// restore original format
	std::cout.setf(original, std::ios_base::floatfield);
	std::cout.precision(precision);
}

const Stock & Stock::TopVal(const Stock & stock) const {
	if (stock.total_val_ > total_val_) {
		return stock;  // argument object
	}
	else {
		return *this;  // invoking object
	}
}

2. An Array of Objects (对象数组)

You declare an array of objects the same way you declare an array of any of the standard types.
声明对象数组的方法与声明标准类型数组相同。

Stock yongqiang[4];  // creates an array of 4 Stock objects

Recall that a program always calls the default class constructor when it creates class objects that aren’t explicitly initialized. This declaration requires either that the class explicitly define no constructors at all, in which case the implicit do-nothing default constructor is used, or, as in this case, that an explicit default constructor be defined. Each element - yongqiang[0], yongqiang[1], and so on - is a Stock object and thus can be used with the Stock methods.
当程序创建未被显式初始化的类对象时,总是调用默认构造函数。上述声明要求,这个类要么没有显式地定义任何构造函数 (在这种情况下,将使用不执行任何操作的隐式默认构造函数),要么定义了一个显式默认构造函数。每个元素 (yongqiang[0]yongqiang[1] 等) 都是 Stock 对象,可以使用 Stock 方法。

yongqiang[0].Update();  // apply Update() to 1st element
yongqiang[3].Show();  // apply Show() to 4th element

const Stock * top = yongqiang[2].TopVal(yongqiang[1]);
// compare 3rd and 2nd elements and set top to point at the one with a higher total value

You can use a constructor to initialize the array elements. In that case, you have to call the constructor for each individual element.
可以用构造函数来初始化数组元素。在这种情况下,必须为每个元素调用构造函数。

const int NUM = 4;
Stock stocks[NUM] = {
	Stock("first", 12.5, 20),
	Stock("second", 200, 2.0),
	Stock("third", 130, 3.25),
	Stock("fourth", 60, 6.5)
};

Here the code uses the standard form for initializing an array: a comma-separated list of values enclosed in braces. In this case, a call to the constructor method represents each value. If the class has more than one constructor, you can use different constructors for different elements.
这里的代码使用标准格式对数组进行初始化:用括号括起的、以逗号分隔的值列表。其中,每次构造函数调用表示一个值。如果类包含多个构造函数,则可以对不同的元素使用不同的构造函数。

const int NUM = 10;
Stock stocks[NUM] = {
	Stock("first", 12.5, 20),
	Stock(),
	Stock("second", 130, 3.25),
};

This initializes stocks[0] and stocks[2] using the Stock(const std::string &company, const long num = 0, const double price = 0.0); constructor as well as stocks[1] using the Stock(); constructor. Because this declaration only partially initializes the array, the remaining seven members are initialized using the default constructor.
上述代码使用 Stock(const std::string &company, const long num = 0, const double price = 0.0); 初始化 stocks[0] and stocks[2],使用构造函数 Stock(); 初始化 stock[1]。由于该声明只初始化了数组的部分元素,因此余下的 7 个元素将使用默认构造函数进行初始化。

初始化对象数组的方案是:首先使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象,然后将临时对象的内容复制到相应的元素中。因此,要创建类对象数组,则这个类必须有默认构造函数。

Because const Stock &TopVal(const Stock &stock) const; examines just two objects at a time, the program uses a for loop to examine the whole array. Also it uses a pointer-to-Stock to keep track of which element has the highest value.
由于 const Stock &TopVal(const Stock &stock) const; 每次只检查两个对象,因此程序使用 for 循环来检查整个数组。另外,它使用 const Stock * top 指针来跟踪值最高的元素。

  • sample.cpp
#include <iostream>

#include "stock.h"

const int NUM = 4;

int main() {

	{
		// Create an array of initialized objects
		Stock stocks[NUM] = {
			Stock("first", 12, 20.0),
			Stock("second", 200, 2.0),
			Stock("third", 130, 3.25),
			Stock("fourth", 60, 6.5)
		};

		std::cout << "\nStock holdings:\n";
		for (int n = 0; n < NUM; ++n) {
			stocks[n].Show();
		}

		// Set pointer to first element
		const Stock * top = &(stocks[0]);
		for (int n = 1; n < NUM; ++n) {
			top = &top->TopVal(stocks[n]);
		}

		// Now top points to the most valuable holding
		std::cout << "\nMost valuable holding:\n";
		top->Show();
	}

	return 0;
}

在这里插入图片描述

Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): first
Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): second
Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): third
Stock::Stock(const std::string &company, const long num = 0, const double price = 0.0): fourth

Stock holdings:
Company: first
  Shares = 12  Share Price = $20.000  Total Worth = $240.00
Company: second
  Shares = 200  Share Price = $2.000  Total Worth = $400.00
Company: third
  Shares = 130  Share Price = $3.250  Total Worth = $422.50
Company: fourth
  Shares = 60  Share Price = $6.500  Total Worth = $390.00

Most valuable holding:
Company: third
  Shares = 130  Share Price = $3.250  Total Worth = $422.50
Stock::~Stock(): fourth
Stock::~Stock(): third
Stock::~Stock(): second
Stock::~Stock(): first
请按任意键继续. . .

Incidentally, knowing about the this pointer makes it easier to see how C++ works under the skin. For example, the original Unix implementation used a C++ front-end cfront that converted C++ programs to C programs.
知道 this 指针就可以更深入了解 C++ 的工作方式。例如,最初的 UNIX 实现使用 C++ 前端 cfront 将 C++ 程序转换为 C 程序。

C++ method definition:

void Stock::Show() const {
	// set format to #.###
	std::ios_base::fmtflags original = std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
	std::streamsize precision = std::cout.precision(3);

	std::cout << "Company: " << company_ << "\n  Shares = " << shares_;
	std::cout << "  Share Price = $" << share_val_;

	// set format to #.##
	std::cout.precision(2);
	std::cout << "  Total Worth = $" << total_val_ << '\n';

	// restore original format
	std::cout.setf(original, std::ios_base::floatfield);
	std::cout.precision(precision);
}

C-style definition:

void Show(const Stock * this) {
	// set format to #.###
	std::ios_base::fmtflags original = std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
	std::streamsize precision = std::cout.precision(3);

	std::cout << "Company: " << this->company_ << "\n  Shares = " << this->shares_;
	std::cout << "  Share Price = $" << this->share_val_;

	// set format to #.##
	std::cout.precision(2);
	std::cout << "  Total Worth = $" << this->total_val_ << '\n';

	// restore original format
	std::cout.setf(original, std::ios_base::floatfield);
	std::cout.precision(precision);
}

That is, it converted a Stock:: qualifier to a function argument that is a pointer to Stock and then uses the pointer to access class members.
Stock:: 限定符转换为函数参数 (指向 Stock 的指针),然后用这个指针来访问类成员。

Similarly, the front end converted function calls like

top.Show();

to this:

Show(&top);

In this fashion, the this pointer is assigned the address of the invoking object. The actual details might be more involved.
将调用对象的地址赋给了 this 指针,实际情况可能更复杂些。

References

[1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/
[2] C++ Primer Plus, 6th Edition, https://www.informit.com/store/c-plus-plus-primer-plus-9780321776402

标签:std,const,val,object,Objects,Array,total,Pointer,Stock
From: https://blog.csdn.net/chengyq116/article/details/140075747

相关文章

  • 关于Java中 因取消装箱可能产生 'NullPointerException' 的原因
    一.什么是装箱,什么是拆箱?装箱:将值类型转换为引用数据类型。拆箱:将引用数据类型转换为值类型。说白了就是Integer与int数据类型之间的转换二.为什么会有自动一说呢?我们都知道,java是一个面向对象的语言。因此包括数字、字符、日期、布尔值等等再内的一切都是对象。但是对......
  • [题解]CF1704D Magical Array
    题意给定\(n\)个长度为\(m\)的数组,对于每一个数组选择下面任意一种操作进行若干次(操作二只能被一个数组选出)。\(c_{t,i}-1,c_{t,i-1}+1,c_{t,j}-1,c_{t,j-1}+1\)。\(c_{t,i}-1,c_{t,i-1}+1,c_{t,j}-1,c_{t,j-2}+1\)。最后输出选择操作二的数组......
  • [题解]CF1312E Array Shrinking
    思路本题为P3146变式,也算是一道很经典的区间DP题了。因为\(n\leq500\),考虑区间DP。定义\(dp_{i,j}\)表示操作\([i,j]\)区间剩余长度的最小值。那么,我们可以枚举一个中间值\(k\),可以显然地得到一个状态转移方程(即不能合二为一的情况):\[dp_{i,j}=\min(dp_{i,......
  • [题解]CF1223F Stack Exterminable Arrays
    CCF出的原题观摩一下。思路首先可以用一个Trie来维护。在这里对本文中的一些变量做一下说明。\(p\)表示当前维护的Trie中,指向的元素编号。\(t_i\)表示在Trie中编号为\(i\)的元素在原序列中的值。\(f_i\)表示在Trie中编号为\(i\)的元素在Trie中的父节点。......
  • httpClient使用GetStringAsync、GetByteArrayAsync、GetStreamAsync三种方法的使用场
     `HttpClient`类中的`GetStringAsync`、`GetByteArrayAsync`和`GetStreamAsync`方法用于从远程服务器获取不同类型的数据。它们的主要使用场景如下:1.`GetStringAsync`方法:-使用场景:当您需要从远程服务器获取文本数据时,可以使用`GetStringAsync`方法。这通常用于......
  • How to get all subarrays from an array by using JavaScript All In One
    HowtogetallsubarraysfromanarraybyusingJavaScriptAllInOneJavaScript动态生成其所有的子数组算法difficulty:Medium/难度:中等solutionsdemos//双指针???//functionnumberOfSubarrays(nums:number[],k:number):number{//letcount=0......
  • 一分钟轻松掌握Java的Vector&ArrayList
    Vector方法是同步的,线程安全ArrayList方法是非同步的,效率较高向量变量的声明格式Vector<向量元素的数据类型>变量名;示例Vectorvs;创建向量实例对象Vectorvs=newVector();在Java中,Vector<Object>是一个泛型Vector,它专门用于存储Object类型或其子类型的对象......
  • 掌握Numpy数组对象ndarray
    Python提供了一个array模块。array和list不同,array直接保存数值,和C语言的一维数组比较类似。但是由于Python的array模块不支持多维,也没有各种运算函数,因此不适合做数值运算。NumPy弥补了Python不支持多维等不足之处,它提供了一种存储单一数据类型的多维数组--ndarray。本次将实......
  • ArrayList并发修改异常
    遇到这么个问题:迭代器并发修改会抛出异常,这个问题之前没有遇到过,特意记录一下: publicstaticvoidmain(String[]args){//创建集合对象List<String>list=newArrayList<String>();//添加元素list.add("hello");list.add("Java......
  • 详谈JavaScript 二进制家族:Blob、File、FileReader、ArrayBuffer、Base64
    详谈JavaScript二进制家族:Blob、File、FileReader、ArrayBuffer、Base64:https://blog.csdn.net/weixin_43025151/article/details/129743443?ops_request_misc=&request_id=&biz_id=102&utm_term=JavaScript%E4%B8%AD%E7%9A%84Blob%E4%BD%A0%E7%9F%A5%E9%81%93%E5%A4%9A%E......