之前我问了一个related, tedious question,现在我发现了一些新东西。
#include <iostream>
#include <string>
using namespace std;
void hello (const string &s1) {
cout << "rocky" << endl;
}
void hello(string &s1) {
cout << "banana" << endl;
}
int main()
{
string s = "abc";
hello(const_cast<const string&>(s)); //how to explain this const_cast?
}
hello(const_cast<const string&>(s));
这适用于并匹配const引用参数函数。那么这次转换怎么样?不是string
到const string&
吗?
当然我知道const引用可以用非const对象初始化......但不知怎的,我从不把它当作转换。我认为这是一项任务。我认为参考的类型和指称的类型是两个截然不同的东西。
答案 0 :(得分:1)
表达式,对象,变量 - 我知道C ++对于新手来说可能有点混乱,特别是当涉及细微的细节时。
所以s
这里是main
中的变量。当main
运行时(这是整个程序,因为它是main
),有一个对应于变量的对象。在main
中,表达式s
引用该对象。但是还有更多表达式引用同一个对象。 (s)
是引用同一对象的另一个表达式。 *&s
也是如此。或*(&s)
。
s+""
是另一个具有相同值的表达式。但它不是同一个对象。参看整数i+0
或i*1
。
引用可用于定义为对象引入新名称的变量,然后可以在表达式中使用的名称。有许多地方可以方便地明确命名。它只是一个新名称,而不是一个新对象。
const_cast
是引用的另一种用途。然而,这并未引入新名称;它只是形成一个新的表达式,并在类型中添加了const
。
现在转到hello
。这是一个过载功能。重载决策是在用作参数的类型的表达式上完成的。因此,在hello(s1)
中,s1
是用于重载解析的简单表达式,其类型为std::string
。在hello(const_cast<std::string const&>(s1))
中,表达式为const_cast<std::string const&>(s1)
,其类型显然为std::string const&
。
两个表达式都引用同一个对象;它们的类型不同。但是,这种类型差异正是重载分辨率所需要的。
答案 1 :(得分:0)
您只能使用const_cast
显式地从const引用转换为左值引用,因为这样的转换不安全且必须是显式的。另一方面,您可以隐式或显式地将左值或左值引用转换为const引用,因为这样的转换是安全的。所以通常没有人明确地转换为const引用,因为它是不必要的冗长而且没有意义。在你的情况下,它被显式转换为选择某个重载函数,因为编译器不会隐式转换它,因为它可以找到带左值引用的重载,但你的例子相当人为,因为很难想象为什么有人会有这样的重载。
答案 2 :(得分:0)
因此,强制转换的主要含义是从重载的hello()函数列表中选择必要的一个。如果没有演员表,我们选择非常量版本,否则它是常量版本。
其次,为什么要引用字符串引用,而不仅仅是字符串类型?这是由于const_cast本身的限制。让我们尝试编译:
hello(const_cast<const string>(s)); // we removed the "&"
编译器消息:
error: invalid use of const_cast with type ‘const string {aka const std::__cxx11::basic_string<char>}’,
which is not a pointer, reference, nor a pointer-to-data-member type
因此,const_cast不是为了创建新实例,而是与间接到给定实例,只是更改相关的CV资格(因为它在代码生成方面是免费的午餐)。因此,我们必须处理指针或引用以符合该条件。
P.S。据我所知,C ++ 17允许为演员创建临时副本(又名临时实现),因此我们的非参考尝试可能具有实际意义。同时,它是一个相当新的概念,并没有那么广泛。