是否可以从子结构调用父结构的方法?

时间:2019-12-16 20:52:15

标签: rust

我试图将对self的引用传递给作为字段变量的子结构

use std::cell::RefCell;
use std::rc::Rc;

pub struct BUS {
    pub processor: CPU,
    pub ram: [u8; 65536],
}

impl BUS {
    pub fn new() -> BUS {
        BUS {
            processor: CPU::new(),
            ram: [0; 65536],
        }
    }

    pub fn setup(&mut self) {
        self.processor.connect_bus(Rc::new(RefCell::new(self)));
        self.ram.iter_mut().for_each(|x| *x = 00);
    }

    pub fn write(&mut self, addr: u16, data: u8) {
        self.ram[addr as usize] = data;
    }

    pub fn read(&mut self, addr: u16, _read_only: bool) -> u8 {
        self.ram[addr as usize]
    }
}

pub struct CPU {
    bus_ptr: Rc<RefCell<BUS>>,
}

impl CPU {
    pub fn new() -> CPU {
        CPU {
            bus_ptr: Rc::new(RefCell::new(BUS::new())),
        }
    }
    pub fn connect_bus(&mut self, r: Rc<RefCell<BUS>>) {
        self.bus_ptr = r;
    }
    pub fn read_ram(&self, addr: u16, _read_only: bool) -> u8 {
        (self.bus_ptr.borrow_mut().read(addr, false))
    }
    pub fn write_ram(&mut self, addr: u16, data: u8) {
        (self.bus_ptr.borrow_mut().write(addr, data))
    }
}

fn main() {
    let comp = BUS::new();
    comp.setup();
}

Rust Playground

此错误:

error[E0308]: mismatched types
  --> src/main.rs:18:57
   |
18 |         self.processor.connect_bus(Rc::new(RefCell::new(self)));
   |                                                         ^^^^ expected struct `BUS`, found &mut BUS
   |
   = note: expected type `BUS`
              found type `&mut BUS`

我无法将self传递给RefCell,因为这是第二次可变借用。我通过移动函数来解决这个问题,但是想知道这种结构的可能性。

我在C ++中实现了这一点,方法是从this传入BUS,然后在*bus中使用connect_bus,这样read_ram就可以成为*bus->read(...)

是否可以从CPU结构上的方法调用BUS结构的readwrite函数?

1 个答案:

答案 0 :(得分:3)

简短的回答是“否”。

  1. RefCell拥有其内部对象。这意味着它拥有该对象的唯一副本,因此它可以完全控制对它的所有访问,并且不允许外部的任何其他访问。对象不能同时存在于RefCellRefCell之外。

    您的setup可以改用现有的Rc<RefCell<BUS>>并传递它。没有包装的&mut BUS不会。

  2. 借阅检查器不能确保父母与子女之间相互关系的安全。它希望将程序数据构造为树或DAG。否则,您将不得不使用包装器类型或类似C的原始指针。

借位检查器将根据接口而不是实现进行检查。如果您的设置者借用了&mut self,那是整个对象的专有借用,对于借阅检查,这是最严格,最不灵活的选择。您需要剥离一些抽象层才能完成这项工作,例如将RAM传递给CPU。或者,使RAM使用Cell<u8>类型,以便可以通过共享引用对其进行突变。