在C++中,阴影变量名称的范围分辨率("优先顺序")是多少?我似乎无法在网上找到简明的答案.
例如:
#include <iostream>
int shadowed = 1;
struct Foo
{
Foo() : shadowed(2) {}
void bar(int shadowed = 3)
{
std::cout << shadowed << std::endl;
// What does this output?
{
int shadowed = 4;
std::cout << shadowed << std::endl;
// What does this output?
}
}
int shadowed;
};
int main()
{
Foo().bar();
}
Run Code Online (Sandbox Code Playgroud)
我想不出变量可能会发生冲突的任何其他范围.如果我错过了,请告诉我.
shadow
在bar
成员函数内部时,所有四个变量的优先级顺序是多少?
阴影类变量的情况在Java中很常见.Eclipse将很乐意生成这段代码:
public class TestClass {
private int value;
private String test;
public TestClass(int value, String test) {
super();
this.value = value;
this.test = test;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
Run Code Online (Sandbox Code Playgroud)
变量阴影是否正常?
我正在考虑实施一个编码规则,说"不允许使用阴影".在上面的简单案例中,很明显发生了什么.添加更多代码来执行某些操作,您可能会错过"this"并引入错误.
普遍的共识是什么?禁止阴影,有时允许它,或让它滚动?
为什么这会给我一个错误?
>>> variable = str(21)
Traceback (most recent call last):
File "<pyshell#101>", line 1, in <module>
variable = str(21)
TypeError: 'str' object is not callable
Run Code Online (Sandbox Code Playgroud) 我知道在命名变量时不使用全局命名空间中的名称是一种好习惯,但是当你意外地执行此操作时会发生什么?
我以为我会丢失之前的对象,但R似乎在引擎盖下有一些诡计:
print(sd)
#> function (x, na.rm = FALSE)
#> sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x),
#> na.rm = na.rm))
#> <bytecode: 0x0000000017e687b8>
#> <environment: namespace:stats>
sd <- 12.2
print(sd)
#> [1] 12.2
sd(1:10)
#> [1] 3.02765
Run Code Online (Sandbox Code Playgroud)
所以现在R知道在全局命名空间中有一个长度为一个双向量调用sd
和一个stats函数sd()
?
或者当我调用sd(1:10)
解释器时自动将其扩展为sd.default()
?但是R如何知道寻找默认方法,sd
因为它现在是一个向量?那么存储在内存中不同位置的函数和变量可以用相同的名称引用吗?
obviously_a_user_defined_variable <- 257
obviously_a_user_defined_variable(1:10)
#> Error in obviously_a_user_defined_variable(1:10): could not find
# function "obviously_a_user_defined_variable"
Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
#include <type_traits>
int main()
{
auto l = [k = 0]
{
static_assert(std::is_same_v<decltype(k), int>);
};
}
Run Code Online (Sandbox Code Playgroud)
clang++
(10.x 和主干)愉快地编译了上面的代码。
g++
(10.x 和主干)无法编译上面的代码并出现以下错误:
Run Code Online (Sandbox Code Playgroud)error: static assertion failed 10 | static_assert(std::is_same_v<decltype(k), int>); | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
显然,g++
相信decltype(k)
评估为const int
。
由于数据成员的类型k
应该从0
(这是一个普通的,非const
, int
)推导出来,我认为这是一个g++
错误。在我的心智模式,这是唯一的事情const
是operator()
拉姆达的,而不是合成的数据成员k
。
我的评估是否正确?
标准怎么说?
直到最近,我一直在使用jQuery和YUI并没有问题.有时候,在YUI按钮的回调中,$
会被其他一些函数遮蔽(点击查看大版本):
而对于我的生活,我无法弄清楚为什么会这样.是的,我知道我可以安全使用jQuery
或window.$
在任何地方而不仅仅是$
,但这只是一种解决方法,而不是一个实际的修复.
在运行时,我怎样才能找到这个$
冒名顶替者的来源? - 例如找到它声明的位置,以及为什么它在我的bleedin范围内.
事实证明,这种行为很容易在Stack Overflow上重现(至少在Chrome和Firefox 4中),因为SO使用jQuery(再次点击查看完整大小):
我只能推断$
为
function () {
return document.getElementById.apply(document, arguments)
}
Run Code Online (Sandbox Code Playgroud)
必须来自控制台本身!
with
再次罢工.
Chromium bug:http://code.google.com/p/chromium/issues/detail?id = 70969
在遇到另一个设计的问题之后,我决定make make一个包装类来向基类的某些成员函数添加重载,当且仅当基类中不存在可行的重载时.基本上,这是我想要做的:
template<typename T>
struct wrapper: T
{
using T::foo;
template<typename Arg>
auto foo(Arg) const
-> std::enable_if_t<not std::is_constructible<Arg>::value, bool>
{
return false;
}
};
struct bar
{
template<typename Arg>
auto foo(Arg) const
-> bool
{
return true;
}
};
Run Code Online (Sandbox Code Playgroud)
在这个简单的例子中,只有当基类中的那个不可行时才wrapper
添加一个重载foo
(我简化std::enable_if
为最简单的东西;原始的一个涉及检测习语).但是,g ++和clang ++不同意.请考虑以下事项main
:
int main()
{
assert(wrapper<bar>{}.foo(0));
}
Run Code Online (Sandbox Code Playgroud)
g ++没关系:foo
from wrapper<bar>
是SFINAEd,所以它使用的是bar
相反的.在另一方面,铛++似乎假定是 wrapper<bar>::foo
永远的阴影bar::foo
,即使SFINAEd出来.这是错误消息:
Run Code Online (Sandbox Code Playgroud)main.cpp:30:26: error: no matching member function for call to 'foo' …
考虑到
object A {
def m(i: Int) = i
val m = (i: Int) => i * 2
}
Run Code Online (Sandbox Code Playgroud)
一个人得到
scala> A.m(2)
<console>: error: ambiguous reference to overloaded definition,
both value m in object A of type => (Int) => Int
and method m in object A of type (i: Int)Int
match argument types (Int)
A.m(2)
^
Run Code Online (Sandbox Code Playgroud)
访问 val
可以完成
scala> val fun = A.m
fun: (Int) => Int = <function1>
scala> fun(2)
res: Int = 4
Run Code Online (Sandbox Code Playgroud)
要么
scala> A.m.apply(2) …
Run Code Online (Sandbox Code Playgroud) 我在其他任何地方都找不到此信息。
在我看来,变量阴影是一个很棒的功能,但是在 Kotlin 中我们每次都会收到警告,因此@Suppress("NAME_SHADOWING")
如果我们不希望它警告我们,我们就需要在它的每个实例中使用它。
有没有办法禁用变量阴影验证,或全局抑制警告?
我可以使用调试隐式的建议:
我想使用隐含的,x
:
type T
trait HasT {
implicit def x: T = ...
}
Run Code Online (Sandbox Code Playgroud)
但我还需要从某个包中导入通配符foo
.我尝试了两种不同的方式来介绍两者:
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
Run Code Online (Sandbox Code Playgroud)
和
class UseT {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
Run Code Online (Sandbox Code Playgroud)
两者都失败了"找不到"(不是"模糊的含义值").
当x: T
通过继承或导入在方法调用点访问隐式标识符时会发生这种情况.
我的解决方法是在导入之前将x重新绑定到隐式val.以下两项工作:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
Run Code Online (Sandbox Code Playgroud)
和
implicit val …
Run Code Online (Sandbox Code Playgroud)