045_对象作用域

1. 公用、私有和受保护作用域

1.1. 在传统的面向对象程序设计中, 主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部访问, 即开发者创建对象的实例后, 就可使用它的公用属性。而私有作用域中的属性只能在对象内部访问, 即对于外部世界来说, 这些属性并不存在。这意味着如果类定义了私有属性和方法, 则它的子类也不能访问这些属性和方法。

1.2. 受保护作用域也是用于定义私有的属性和方法, 只是这些属性和方法还能被其子类访问。

2. JavaScript只有公用作用域

2.1. 对JavaScript讨论上面这些作用域几乎毫无意义, 因为JavaScript中只存在一种作用域, 公用作用域。JavaScript中的所有对象的所有属性和方法都是公用的。因此, 定义自己的类和对象时, 必须格外小心。记住, 所有属性和方法默认都是公用的!

3. 建议性的解决方法

3.1. 许多开发者都在网上提出了有效的属性作用域模式, 解决了JavaScript的这种问题。

3.2. 由于缺少私有作用域,开发者确定了一个规约,说明哪些属性和方法应该被看做私有的。这种规约规定在属性前后加下划线:

obj._color_ = "blue";

3.3. 这段代码中, 属性color是私有的。注意, 下划线并不改变属性是公用属性的事实, 它只是告诉其他开发者, 应该把该属性看作私有的。

4. 静态作用域

4.1. 静态作用域定义的属性和方法任何时候都能从同一位置访问。在Java中, 类可具有属性和方法, 无需实例化该类的对象, 即可访问这些属性和方法, 例如: java.net.URLEncoder类, 它的函数encode()就是静态方法。

4.2. JavaScript没有静态作用域

4.2.1. 严格来说, JavaScript并没有静态作用域。不过, 它可以给构造函数提供属性和方法。还记得吗, 构造函数只是函数。函数是对象, 对象可以有属性和方法。例如:

function sayHello() {
    alert("hello");
}

sayHello.alternate = function() {
    alert("hi");
}

sayHello();     // 输出"hello"
sayHello.alternate();   // 输出"hi"

4.2.2. 这里, 方法alternate()实际上是函数sayHello的方法。可以像调用常规函数一样调用sayHello()输出"hello", 也可以调用sayHello.alternate()输出"hi"。即使如此, alternate()也是sayHello() 公用作用域中的方法, 而不是静态方法。

5. 关键字this

5.1. this的功能

5.1.1. 在JavaScript中, 要掌握的最重要的概念之一是关键字this的用法, 它用在对象的方法中。关键字this总是指向调用该方法的对象, 例如:

var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
  alert(this.color);
};

oCar.showColor();       // 输出"red"

5.1.2. 在上面的代码中, 关键字this用在对象的showColor()方法中。在此环境中, this等于oCar。下面的代码与上面的代码的功能相同:

var oCar = new Object;
oCar.color = "red";
oCar.showColor = function() {
  alert(oCar.color);
};

oCar.showColor();       // 输出"red"

5.2. 使用this的原因

5.2.1. 为什么使用this呢?因为在实例化对象时, 总是不能确定开发者会使用什么样的变量名。使用this, 即可在任何多个地方重用同一个函数。请思考下面的例子:

function showColor() {
    alert(this.color);
};

var oCar1 = new Object;
oCar1.color = "red";
oCar1.showColor = showColor;

var oCar2 = new Object;
oCar2.color = "blue";
oCar2.showColor = showColor;

oCar1.showColor();      // 输出"red"
oCar2.showColor();      // 输出"blue"

5.2.2. 在上面的代码中, 首先用this定义函数showColor(), 然后创建两个对象(oCar1和oCar2), 一个对象的color属性被设置为"red", 另一个对象的color属性被设置为"blue"。两个对象都被赋予了属性showColor, 指向原始的showColor()函数(注意这里不存在命名问题, 因为一个是全局函数, 而另一个是对象的属性)。调用每个对象的showColor(), oCar1输出是"red", 而oCar2的输出是"blue"。这是因为调用oCar1.showColor() 时, 函数中的this关键字等于oCar1。调用oCar2.showColor()时, 函数中的this关键字等于oCar2。

5.2.3. 注意, 引用对象的属性时, 必须使用this关键字。例如, 如果采用下面的代码, showColor()方法不能运行:

function showColor() {
    alert(color);
};

5.2.4. 如果不用对象或this关键字引用变量, JavaScript就会把它看作局部变量或全局变量。然后该函数将查找名为color的局部或全局变量, 但是不会找到。结果如何呢?该函数将在警告中显示"null"。

### lock_guard 的作用域 `std::lock_guard` 是 C++11 引入的一个轻量级模板类,用于实现 RAII(资源获取即初始化)机制,以确保在多线程环境中对互斥量(`std::mutex`)的正确加锁和解锁。`lock_guard` 的作用域决定了其对互斥量的锁定和解锁行为。具体来说: - **作用域绑定**:`lock_guard` 对象在其构造时对指定的互斥量加锁,并在其析构时自动解锁互斥量。因此,其锁定的持续时间完全取决于其作用域——一旦对象超出作用域,互斥量就会被自动释放[^3]。 - **局部作用域控制**:可以通过将 `lock_guard` 对象定义在特定的代码块(如一对 `{}` 括起来的代码段)中,来精确控制锁定的范围。这样可以在一个函数中多次使用 `lock_guard` 来锁定同一个互斥量,而不会导致死锁[^5]。 ### lock_guard 的使用方法 `std::lock_guard` 提供了两种主要的构造方式,分别适用于不同的使用场景: 1. **直接加锁构造**: ```cpp std::mutex mtx; { std::lock_guard<std::mutex> lck(mtx); // 执行需要同步保护的代码 } // lck 超出作用域后自动解锁 ``` 在此构造方式下,`lock_guard` 会在构造时自动调用 `mtx.lock()` 方法对互斥量进行加锁,而在 `lck` 对象超出作用域时自动调用 `mtx.unlock()` 方法进行解锁[^1]。 2. **已加锁构造**: ```cpp std::mutex mtx; mtx.lock(); { std::lock_guard<std::mutex> lck(mtx, std::adopt_lock); // 执行需要同步保护的代码 } // lck 超出作用域后自动解锁 ``` 此构造方式要求互斥量在传递给 `lock_guard` 之前已经被当前线程锁定。构造 `lock_guard` 时不会再次加锁,而是接管已有的锁状态,并在对象析构时负责解锁。这种方式适用于需要在多个代码段之间共享锁的情况[^2]。 ### 使用示例 以下是一个完整的示例,演示了如何使用 `std::lock_guard` 来保护共享资源的访问: ```cpp #include <iostream> #include <thread> #include <vector> #include <mutex> std::mutex mtx; int shared_counter = 0; void increment_counter() { for (int i = 0; i < 1000; ++i) { std::lock_guard<std::mutex> lock(mtx); ++shared_counter; } } int main() { std::vector<std::thread> threads; for (int i = 0; i < 10; ++i) { threads.emplace_back(increment_counter); } for (auto& t : threads) { t.join(); } std::cout << "Final counter value: " << shared_counter << std::endl; return 0; } ``` 在这个示例中,`increment_counter` 函数中的 `std::lock_guard` 确保了对 `shared_counter` 的原子性递增操作。每个线程执行 `increment_counter` 函数时都会对 `mtx` 进行加锁,从而防止其他线程同时修改 `shared_counter`,保证了数据的一致性和完整性[^4]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值