Destructor naming 析构函数
Like constructors, destructors have specific naming rules:
- The destructor must have the same name as the class, preceded by a tilde (~).
- The destructor can not take arguments.
- The destructor has no return type
析构函数将类中的说用到的资源,动态分配空间,数据库,文件流等在函数结束时进行释放清除,自动释放,普通数据类型变量无需使用使用析构函数
The hidden “this” pointer
“this”指针
class Simple
{
private:
int m_id;
public:
Simple(int id)
: m_id{ id }
{
}
void setID(int id) { m_id = id; }
int getID() { return m_id; }
};
int main()
{
Simple simple{1};
simple.setID(2);
std::cout << simple.getID() << '\n';
return 0;
}
当成员函数被调用时内部会发生一定的变化
void setID(int id) { m_id = id; }
is converted by the compiler into:
void setID(Simple* const this, int id) { this->m_id = id; }
When the compiler compiles a normal member function, it implicitly adds a new parameter to the function named “this”. The this pointer is a hidden const pointer that holds the address of the object the member function was called on.
-
When we call simple.setID(2), the compiler actually calls setID(&simple, 2).
成员函数被默认为传递了类的地址
-
Inside setID(), the “this” pointer holds the address of object simple.
-
Any member variables inside setID() are prefixed with “this->”. So when we say m_id = id, the compiler is actually executing this->m_id = id, which in this case updates simple.m_id to id.
“this” always points to the object being operated on
int main()
{
Simple A{1}; // this = &A inside the Simple constructor
Simple B{2}; // this = &B inside the Simple constructor
A.setID(3); // this = &A inside member function setID
B.setID(4); // this = &B inside member function setID
return 0;
}
that the “this” pointer alternately holds the address of object A or B depending on whether we’ve called a member function on object A or B.
“this”使用
一般不要使用 this 指针,如果有重名用加前缀的方式好过于加this指针
if you have a constructor (or member function) that has a parameter with the same name as a member variable, you can disambiguate them by using “this”:
class Something
{
private:
int data;
public:
Something(int data)
{
this->data = data; // this->data is the member, data is the local parameter
}
};
that our constructor is taking a parameter of the same name as a member variable. In this case, “data” refers to the parameter, and “this->data” refers to the member variable
std::cout << "Hello, " << userName;
(std::cout << "Hello, ") << userName;
First, operator<< uses std::cout and the string literal “Hello, ” to print “Hello, ” to the console. However, since this is part of an expression, operator<< also needs to return a value (or void)
perator<< returns *this, which in this context is the std::cout object. That way, after the first operator<< has been evaluated, we get:
(std::cout) << userName;
In this way, we only need to specify the object (in this case, std::cout) once, and each function call passes it on to the next function to work with, allowing us to chain multiple commands together
this 另外的用法
class Calc
{
private:
int m_value{0};
public:
void add(int value) { m_value += value; }
void sub(int value) { m_value -= value; }
void mult(int value) { m_value *= value; }
int getValue() { return m_value; }
};
#include <iostream>
int main()
{
Calc calc{};
calc.add(5); // returns void
calc.sub(3); // returns void
calc.mult(4); // returns void
std::cout << calc.getValue() << '\n';
return 0;
}
程序冗长,函数调用了三次,可用this进行浓缩
class Calc
{
private:
int m_value{};
public:
Calc& add(int value) { m_value += value; return *this; }
Calc& sub(int value) { m_value -= value; return *this; }
Calc& mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
#include <iostream>
int main()
{
Calc calc{};
calc.add(5).sub(3).mult(4);
std::cout << calc.getValue() << '\n';
return 0;
}
程序变为了一行
First, calc.add(5) is called, which adds 5 to our m_value. add() then returns *this, which is just a reference to calc, so calc will be the object used in the subsequent evaluation. Next calc.sub(3) evaluates, which subtracts 3 from m_value and again returns calc. Finally, calc.mult(4) multiplies m_value by 4 and returns calc, which isn’t used further, and is thus ignored.
Since each function modified calc as it was executed, calc’s m_value now contains the value (((0 + 5) - 3) * 4), which is 8.
将类的定义放在头文件中,下面是一些建议
For classes used in only one file that aren’t generally reusable, define them directly in the single .cpp file they’re used in.
For classes used in multiple files, or intended for general reuse, define them in a .h file that has the same name as the class.
Trivial member functions (trivial constructors or destructors, access functions, etc…) can be defined inside the class.
Non-trivial member functions should be defined in a .cpp file that has the same name as the class.