首页 > 解决方案 > C ++将类传递给构造函数=不传递相同的实例?

问题描述

似乎,当我传递一个类时,它并没有像我期望的那样传递该类的持久(相同)实例。我假设这与记忆状态有关,但如果有人能准确解释正在发生的事情,我将不胜感激。该问题很容易证明如下:

主程序

#include "Debug.h"
#include "Box.h"

Debug debug;
Box box(debug);

void loop(){
  debug.message("loop");
  debug.line();
}

void setup(){
  debug.init();
  box.init();
  debug.message("Setup Complete");
  debug.line();
}

调试.h

#ifndef DEBUG_H
#define DEBUG_H

class Debug {
  private:
    bool state;
  public:
    Debug();
    void init();
    void message(const char *str);
    void message(int);
    void line();
};

#endif

调试.cpp

#include "Debug.h"
#include <Arduino.h>

Debug::Debug() : state(false) {}

void Debug::init() {
  if (state == false){
    Serial.begin(9600);
    state = true;
  }
}
void Debug::message(const char *messageChar) {
  if (state){
    const char *p;
    p = messageChar;
    while (*p) {
        Serial.print(*p);
        p++;
    }
  }
}
void Debug::message(int messageInt) {
  if (state){
    Serial.print(messageInt);
  }
}
void Debug::line() {
  if (state){
    Serial.println();
  }
}

盒子.h

#ifndef BOX_H
#define BOX_H

#include "Debug.h"

class Box {  
  private:
    Debug debug;
  public:
    Box(Debug &debug);
    void init();
};

#endif

盒子.cpp

#include "Box.h"
#include <Arduino.h>

Box::Box(Debug &debug):
  debug(debug)
{}

void Box::init(){
  // Switches
  pinMode(28, INPUT_PULLUP);

  debug.message("Box intialized");
  debug.line();
}

所以上面的代码输出到串口:

Setup Complete

如果我将 Box::init() 修改为

void Box::init(){
  // Switches
  pinMode(28, INPUT_PULLUP);

  debug.init();
  debug.message("Box intialized");
  debug.line();
}

我得到了我想要的:

Box initialized
Setup Complete

如果我摆脱 Box 构造函数类,而是做

void Box::init(Debug &debug){
  this->debug = debug;
  
  // Switches
  pinMode(28, INPUT_PULLUP);

  debug.message("Box intialized");
  debug.line();
}

通过 Main.ino 调用

void setup(){
  debug.init();
  box.init(debug);
  debug.message("Setup Complete");
  debug.line();
}

我再次得到了想要的回应。我不明白为什么我的第一次尝试不起作用,也不知道什么是最佳实践让我感到不舒服。我将不胜感激任何指导。

标签: c++arduino

解决方案


您的代码中有两个Debug值。一个全局,一个Box类的成员。

这是两个不同的值,因为Box从一个值创建或复制以创建它自己的值,并且是全局值。

一种解决方案是包含引用或指针。

这是带有参考的示例:

class Box {  
  private:
    Debug& debug;
    //   ^---- there
  public:
    Box(Debug &debug);
    void init();
};

如果您Box仍然想分配,请使用指针:

class Box {  
  private:
    Debug* debug;
    //   ^---- now it's a star
  public:
    Box(Debug &debug);
    void init();
};

Box::Box(Debug &debug):
  debug(&debug)
{} //   ^----- here, we take the address of the debug variable.

由于引用是不可变的,因此您失去了该语言的一些重要特性:赋值。

struct thing {
    int& ref;
};

int main () {
    int a, b;
    thing t1{a}, t2{b};

    t1 = t2; // ERROR!
}

赋值会导致t1.ref指向b后赋值。

指针具有更难的语法和难以猜测的语义。但是,它们在分配方面表现得非常好,因为它们给了你更多的自由:

struct thing {
    int* ptr;
};

int main () {
    int a, b;
    thing t1{&a}, t2{&b};

    t1 = t2; // Works, t1.ptr points to b
}

推荐阅读