本文主要是介绍Cherno C++系列笔记12——P40~P41 隐式转换与explicit关键字、运算符及其重载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1.P40 隐式转换于explicit关键字
- 1.1.隐式类型转换(隐式构造函数)
- 1.2.explicit关键字禁止隐式类型转换
- 2.P41 运算符及其重载
1.P40 隐式转换于explicit关键字
参考:视频 笔记
1.1.隐式类型转换(隐式构造函数)
隐式转换的意思是不会明确的告诉编译器要怎么做,像是编译器通过上下文自动推导要做的事情。
C++允许编译器对代码执行一次隐式转换,在两个类型之间C++允许进行隐式转换,而不需要用cast做强制转换,类型转换是将数据类型转换到另一个类型的过程。
如下代码所示,将a赋值为herno,b直接等于22(Java,C#等其他语言不行)。这被称为隐式转换,或者叫隐式构造函数。它隐式地将22转换成一个Entity并构造出一个Entity,因为有一个Entity的构造函数接受一个整数的参数。另一个构造函数接受的字符串name是”Cherno”作为参数。
由于Entity
这个类有两个构造函数,分别传入stirng和int作为形参,所以就可以直接写Entity a = "Cherno"; Entity b = 22;
,使用string和int类型的数据直接构造Entity对象,这里C++编译器就进行了一次隐式类型转换。
ps:注意在VS2019 MSVC C++14环境下Entity a = “Cherno”;
会报错,因为字符串字面量"Cherno"
在编译器中认为是const char*
,而Entity
类的构造函数形参为string类,所以这里存在const char*
-> string
-> Entity
两次类型转化,而C++只允许一次隐式类型转换。
#include<iostream>
#include<string>class Entity
{
private:std::string m_Name;int m_Age;
public:Entity(const std::string& name):m_Name(name), m_Age(-1) {}Entity(int age):m_Name("Unknown"), m_Age(age) {}
};int main()
{// 1.正常的写法,不包含隐式转换//Entity a("Cherno");//Entity b(22);//Entity a = Entity("Cherno");//Entity b = Entity(22);// 2.使用隐式转换的写法Entity a = "Cherno";Entity b = 22;std::cin.get();
}
同样的隐式类型转换还可以发生在函数参数传递的过程中:创建一个PrintEnti函数用来做打印,参数是entity。我们可以直接调用这个函数,参数为22。因为C++认为22可以转换成一个Entity(隐式转换),可以调用这个构造函数,22是创建Entity的唯一参数。PrintEntity(“Cherno”);
则会报错,因为"Cherno"不是std::string
而是char数组。所以C++需要2次转换,一个从const char
数组到string
,一个从string
到Entity
。但因为只允许做一次隐式转换,所以必须把它包装在一共构造函数中,或者包装在一个Entity对象中(隐式地将这个字符串转换为std:string标准字符串,然后推入Entity构造函数)。
void PrintEntity(const Entity& entity)
{// Printing
}int main()
{PrintEntity(22); PrintEntity("Cherno"); // 报错PrintEntity((std::string)"Cherno"); // 编译通过PrintEntity(Entity("Cherno")); std::cin.get();
}
1.2.explicit关键字禁止隐式类型转换
explicit与隐式转换有关,因为explicit禁用这个隐式转换的功能,explicit关键字放在构造函数前面表示没有隐式的转换。如果要使用整数构造这个Entity对象,则必须显式调用此构造函数。
把explicit放在int age构造函数前面,则会发现PrintEntity(22); 和Entity b = 22;都失败了。
若把explicit放在第一个构造函数前面,第25行同样会失败。但是24行会成功,因为它实际上调用了构造函数。
2.P41 运算符及其重载
参考:视频 笔记
运算符重载这个也比较基础,没有什么新的内容。其中重载<<
流运算符的例子可以看一下,输入和输出都是std::ostream
的引用&
是为了实现<<
流运算符的链式法则,这个在《21天学通C++》中有讲解。
#include<iostream>
#include<string>struct Vector2
{float x, y;Vector2(float x, float y):x(x), y(y) {}Vector2 Add(const Vector2& other) const{return Vector2(x + other.x, y + other.y);}Vector2 Multiply(const Vector2& other) const{return Vector2(x * other.x, y * other.y);}Vector2 operator+(const Vector2& other) const{return Add(other);}Vector2 operator*(const Vector2& other) const{return Multiply(other);}
};// 重载<<
std::ostream& operator<<(std::ostream& stream, const Vector2& other)
{stream << other.x << "," << other.y;return stream;
}int main()
{Vector2 position(4.0f, 4.0f);Vector2 speed(0.5f, 1.5f);Vector2 powerup(1.1f, 1.1f);Vector2 result2 = position + speed * powerup;std::cout << result2 << std::endl;std::cin.get();
}
在使用std::cout我们会用到左移运算符,它接受2个参数。一个是输出流cout,另一个是vector2。我们需要在vector2类的外面将<<运算符重载。它和vector2没有任何关系,我们是在cout中重载。我们写上std::ostream&
输出流,是一个引用。这是我们需要重载符号的最初定义,然后写一个operator加上左移运算符,然后需要一个对现有流的引用,传入const vector2通过引用传递。
这篇关于Cherno C++系列笔记12——P40~P41 隐式转换与explicit关键字、运算符及其重载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!