Hippy项目源码分析补充(三)

本文详细介绍了C++中类的Scope概念,包括名字域的可见范围、类的作用域以及成员访问。讲解了如何在类内外访问成员函数和类型,强调每个类都有其独立的作用域,并通过示例展示了成员函数定义和类型引用的方法。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

Scope.h

#pragma once

#include <string>
#include <unordered_map>

#include "base/unicode_string_view.h"
#include "core/base/common.h"
#include "core/base/task.h"
#include "core/base/uri_loader.h"
#include "core/engine.h"
#include "core/napi/js_native_api.h"
#include "core/napi/js_native_api_types.h"
#include "core/task/worker_task_runner.h"

class JavaScriptTaskRunner;
class ModuleBase;
class Scope;

class ScopeWrapper {
 public:
  explicit ScopeWrapper(std::shared_ptr<Scope> scope) : scope_(scope) {}

 public:
  std::weak_ptr<Scope> scope_;
};

class Scope {
 public:
  using unicode_string_view = tdf::base::unicode_string_view;
  using RegisterMap = hippy::base::RegisterMap;
  using CtxValue = hippy::napi::CtxValue;
  using Ctx = hippy::napi::Ctx;
  using UriLoader = hippy::base::UriLoader;
  using FunctionData = hippy::napi::FunctionData;
  using BindingData = hippy::napi::BindingData;
  using Encoding = hippy::napi::Encoding;

  Scope(Engine* engine,
        std::string  name,
        std::unique_ptr<RegisterMap> map);
  ~Scope();

  void WillExit();
  inline std::shared_ptr<Ctx> GetContext() { return context_; }
  inline std::unique_ptr<RegisterMap>& GetRegisterMap() { return map_; }

  ModuleBase* GetModuleClass(const unicode_string_view& moduleName);
  void AddModuleClass(const unicode_string_view& name,
                      std::unique_ptr<ModuleBase> module);
  std::shared_ptr<CtxValue> GetModuleValue(
      const unicode_string_view& moduleName);
  void AddModuleValue(const unicode_string_view& name,
                      const std::shared_ptr<CtxValue>& value);

  void SaveFunctionData(std::unique_ptr<FunctionData> data);

  inline void SaveBindingData(std::unique_ptr<BindingData> data) {
    binding_data_ = std::move(data);
  }

  inline const std::unique_ptr<BindingData>& GetBindingData() {
    return binding_data_;
  }

  void RunJS(const unicode_string_view& js,
             const unicode_string_view& name,
             bool is_copy = true);

  std::shared_ptr<CtxValue> RunJSSync(const unicode_string_view& data,
                                      const unicode_string_view& name,
                                      bool is_copy = true);

  inline std::shared_ptr<JavaScriptTaskRunner> GetTaskRunner() {
    return engine_->GetJSRunner();
  }

  inline std::shared_ptr<WorkerTaskRunner> GetWorkerTaskRunner() {
    return engine_->GetWorkerTaskRunner();
  }

  inline void AddTask(std::unique_ptr<hippy::base::Task> task) {
    std::shared_ptr<JavaScriptTaskRunner> runner = engine_->GetJSRunner();
    if (runner) {
      runner->PostTask(std::move(task));
    }
  }

  inline void SetUriLoader(std::shared_ptr<UriLoader> loader) {
    loader_ = loader;
  }

  inline std::shared_ptr<UriLoader> GetUriLoader() { return loader_; }

 private:
  friend class Engine;
  void Initialized();

 private:
  Engine* engine_;
  std::shared_ptr<Ctx> context_;
  std::string name_;
  std::unique_ptr<RegisterMap> map_;
  std::unordered_map<unicode_string_view, std::shared_ptr<CtxValue>>
      module_value_map_;
  std::unordered_map<unicode_string_view, std::unique_ptr<ModuleBase>>
      module_class_map_;
  std::vector<std::unique_ptr<FunctionData>> function_data_;
  std::unique_ptr<BindingData> binding_data_;
  std::unique_ptr<ScopeWrapper> wrapper_;
  std::shared_ptr<UriLoader> loader_;
};

C++类的scope简析:

首先来说说 名字的域 (或者说是C++语言里面的那些名字标识符的可见范围)

在程序的任意代码位置上,每一个被使用到的名字或者标识符指代一个实体,比如变量名,函数名,类型名等等。然而 同一个名字可以被重复使用用来指代不同代码作用域里的不同实体。

域指的是程序的某部分,在程序的这个部分里面,一个名字有它的特定含义。在C++里,不同的域是通过 用 { } 这个 括号来隔开的。

同一个名字可以指代在不同域里面的名字。那么名字的可见范围是从它的声明开始到 声明这个名字的域的结束位置为止。

每一个类拥有它自己的一个新scope。如果在类的scope 范围外,通常的数据成员或者函数成员可以通过 使用成员访问操作符作用在该类的 对象,引用,或者指针上来达到访问的目的。当要访问类的类型成员,可以使用域操作符。 不管使用哪种操作符,跟在操作符后面的那个名字一样的标识符必须是该类的成员。 比如如下:

Screen::pos ht = 24, wd = 80; // use the pos type defined by Screen

Screen scr(ht, wd, ' ')

Screen *p = &scr;

char c = scr.get(); // fetches the get member from the object scr

c = p->get(); // fetches the get member from the object to which p points

正因为每一个类定义一个它自己全新的域,所以在类的定义(或者说作用域之外)如果想要定义该类的一个成员函数,必须要加上类名和函数名字,因为在类的域外,成员的名字是被隐藏了的。

只要类名被编译器识别到了,剩下的定义--包括参数列表和函数体--都在类的作用域里面。因此可以不需要类名就可以引用其他的类成员。

class Window_mgr

{

public:

using ScreenIndex = std::vector<Screen>::size_type;

void clear(ScreenIndex);

private:

std::vector<Screen> screens{Screen(24, 80, ' ')};

};

void Window_mgr::clear(ScreenIndex i)

{

Screen &s = screens[i];

s.contents = string(s.height * s.width, ' ');

}

像上面的clear 成员函数用到了Window_mgr域内定义的类型 ScreenIndex, 因为编译器是在知道了当前处于 Window_mgr 类域里面后才发现clear 成员函数的参数列表的,因此不需要多此一举说明 要使有 Window_mgr类里面定义的 ScreenIndex 类型。同理 screens 的使用也是同一个道理。

然而,由于成员函数的返回类型是出现在成员函数名的前面的,所以当成员函数是在类外面定义的时候,任何的返回值类型同样也是在类之外的域。 这样的话,返回值类型必须要声明该类型是哪个域的。

class Window_mgr

{

public:

ScreenIndex addScreen(const Screen&);

};

Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s)

{

}

从上面的addScreen 函数的例子可以看到,由于返回值类型出现在类名之前,那么就不再 该类的作用域里,所以为了使用该类定义的类型,就必须加上 Window_mgr 用来指代使用的是该类的自定义类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值