[C++ learning] classes and objects | talk about constructors | implicit type conversion in constructors | static static members

Table of contents

1. Talk about the constructor again

2. Implicit type conversion in constructor

3. static static member

Write at the end:


1. Talk about the constructor again

We initialized earlier using the constructor:

#include <iostream>
using namespace std;

class Date {
public:
	Date(int year = 2023, int month = 7, int day = 1) {
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;

	return 0;
}

The use is to assign values ​​​​in the function body of the constructor,

In fact, there is another initialization method for constructors, which is list initialization.

Look at the code:

#include <iostream>
using namespace std;

class Date {
public:
	Date(int year = 2023, int month = 7, int day = 1) 
		: _year(year)
		, _month(month)
		, _day(day)
	{}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;

	return 0;
}

In fact, the effects of these two initialization methods are the same.

The initialization list starts with a colon and is separated by commas.

Here are a few things to note:

1. Each member variable can only appear once in the initialization list at most,

2. Some members must be initialized in the initialization list:

Reference member variables, const member variables, custom type members.

So why?

In fact, reference member variables and const member variables need to be initialized at definition time,

While assigning a value in the function body, the compiler does not consider it to be initialized at the time of definition.

The use of the initialization list is initialized at the time of definition,

Remember what we learned before, the default value added when the function member variable is declared?

That is automatically called when the list is initialized.

And for custom, use list initialization:

#include <iostream>
using namespace std;

class A {
public:
	A(int a)
		: _a(a)
	{}

private:
	int _a;
};

class B {
public:
	B(int a = 10)
		: _a(a)
	{}

private:
	A _a;
};

int main()
{
	B b;
	B b(20);

	return 0;
}

In this way, when the object of B is created, the initialization of the object of class A can be controlled outside,

Of course, you can also choose not to control, and you can feel that such code can be more flexible.  

There is another point to note about the initialization list:

Look at this question:

#include <iostream>
using namespace std;

class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}

	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}

private:
	int _a2;
	int _a1;
};
int main() 
{
	A aa(1);
	aa.Print();
} 

// A.输出1 1
// B.程序崩溃
// C.编译不通过
// D.输出1 随机值

For this code, we must not choose C, because there are no syntax errors,

And we can't choose B, because only things like null pointers, out-of-bounds access, etc. can crash,

And we shouldn't choose A, because in general, isn't it too easy to choose A,

Then why choose D as the answer, and output 1 and a random value?

Because the initialization order of the initialization list is not initialized in the order you initialized,

He is initialized in the order in which member variables are declared ,

So this code will initialize _a2 first, and _a1 is still a random value, so the value of _a2 is initialized to a random value,

Then initialize _a1 to 1, so output 1 and a random value. 

2. Implicit type conversion in constructor

Such an operation is supported in C++:

#include <iostream>
using namespace std;

class A {
public:
	A(int a = 10)
		: _a(a)
	{}

private:
	int _a;
};

int main()
{
	A a1(20);
	A a2 = 20;

	return 0;
}

Obviously A is a custom type, why can he = a number of type int?

In fact, we have learned implicit type conversion in C language:

double a = 10;

The compiler generates a double-type temporary variable from the plastic copy of 10, and then assigns it to a.

And the above code is similar logic,

First use 20 as a parameter to construct a temporary variable of type A,

Then a2 copy constructs this object with parameter 20.

At this time, you may have doubts, what is the use of this feature?

Consider this example:

#include <iostream>
#include <string>
using namespace std;

int main()
{
	string s1("你好");
	string s2 = "你好"; //隐式类型转换

	return 0;
}

When using the string class, we can use the constructor to convert the string "Hello",

Convert to string type, you can also use = to use directly through implicit type conversion,

At this time, you may have doubts again. These two methods seem to be inconvenient.

Let's continue with this example:

#include <iostream>
#include <string>
using namespace std;

class list {
public:
	void push_back(const string& str) {

	}
};

int main()
{

	list st;

	string s1("你好");
	st.push_back(s1);

	st.push_back("你好"); //隐式类型转换

	return 0;
}

The push_back interface of this list class needs to pass parameters of type string,

If we don't have implicit type conversion, we have to construct a string class first, and then call this interface,

If there is implicit type conversion, we can pass a string directly,

Then the compiler helps us convert to the string class through implicit type conversion to pass parameters, which is much more convenient.

Then here is a keyword by the way:

Keyword explicit:

Implicit type conversions cannot be performed using this keyword:

 As you can see, an error will be reported if the implicit type conversion is performed.

3. static static member

Consider this example:

#include <iostream>
using namespace std;

class A {
public:
	A(int a = 10)
		: _a(a)
	{}

private:
	int _a;

	static int _num;
};

int A::_num = 0;

int main()
{
	A a1(20);
	A a2 = 20;

	return 0;
}

Static member variables cannot be defined within a class,

It needs to be defined outside the class, which is this: int A::_num = 0

And what is the difference between static members and ordinary member variables?

Member variables belong to each instantiated class object and are stored in the object;

The static member variables belong to each class, and each object of the class is shared and stored in the static area.

In addition to static member variables, there are also static member functions,

Let's see an example:

#include <iostream>
using namespace std;

class A {
public:
	A(int a = 10)
		: _a(a)
	{}

	static void Print() {
		cout << "I am static" << endl;
	}

private: 
	int _a;

	static int _num;
};

int A::_num = 0;

int main()
{
	A a1(20);
	A a2 = 20;

	A::Print();

	return 0;
}

output:

I am static

Static member functions do not have a this pointer,

It can be accessed directly by specifying the class field and access qualifier.

Then let's practice it:

If we want to design a class, what should we do if we can only create objects on the stack/heap outside the class?

Look at the code:

#include <iostream>
using namespace std;

class A {
public:
	A(int a = 10)
		: _a(a)
	{}

private: 
	int _a;
};

int main()
{
	static A a;

	return 0;
}

If it is just an ordinary class, this creates an object on the static area,

So how to limit it?

We can make the constructor private:

#include <iostream>
using namespace std;

class A {
public:

private:
	A(int a = 10)
		: _a(a)
	{}

private: 
	int _a;
};

int main()
{
	A a;         //在栈上开辟
	A* a = new A; //在堆上开辟

	return 0;
}

Now, although the static area can no longer be created, you can no longer create objects anywhere.

Because the constructor can only be called within the class, what should I do?

At this time, the static static member function can appear:

#include <iostream>
using namespace std;

class A {
public:
	static A* GetHeap() {
		return new A;
	}

	static A& GetStack() {
		A a;
		return a;
	}

private:
	A(int a = 10)
		: _a(a)
	{}

private: 
	int _a;
};

int main()
{
	//A a;          //在栈上开辟
	//A* a = new A; //在堆上开辟

	A::GetStack(); //在栈上开辟
	A::GetHeap();  //在堆上开辟

	return 0;
}

You see, we use static member functions to solve it all at once.

Write at the end:

The above is the content of this article, thank you for reading.

If you feel that you have gained something, you can give the blogger a like .

If there are omissions or mistakes in the content of the article, please private message the blogger or point it out in the comment area~

Guess you like

Origin blog.csdn.net/Locky136/article/details/131487304