C++ 将 class 传递给构造函数 = 不传递相同的实例?
C++ passing class to constructor = not passing same instance?
似乎,当我传递 class 时,它并没有像我期望的那样传递 class 的持久(相同)实例。我假设这与内存状态有关,但如果有人能准确解释正在发生的事情,我将不胜感激。这个问题很容易证明如下:
Main.ino
#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();
}
Debug.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
Debug.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();
}
}
Box.h
#ifndef BOX_H
#define BOX_H
#include "Debug.h"
class Box {
private:
Debug debug;
public:
Box(Debug &debug);
void init();
};
#endif
Box.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 构造函数 class 而改为
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();
}
我又得到了想要的回复。我不明白为什么我的第一次尝试不起作用,也不明白什么是最佳实践。我将不胜感激任何指导。
您的代码中有两个 Debug
值。一个全球,一个成员 Box
class.
这是两个不同的值,因为 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
}
似乎,当我传递 class 时,它并没有像我期望的那样传递 class 的持久(相同)实例。我假设这与内存状态有关,但如果有人能准确解释正在发生的事情,我将不胜感激。这个问题很容易证明如下:
Main.ino
#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();
}
Debug.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
Debug.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();
}
}
Box.h
#ifndef BOX_H
#define BOX_H
#include "Debug.h"
class Box {
private:
Debug debug;
public:
Box(Debug &debug);
void init();
};
#endif
Box.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 构造函数 class 而改为
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();
}
我又得到了想要的回复。我不明白为什么我的第一次尝试不起作用,也不明白什么是最佳实践。我将不胜感激任何指导。
您的代码中有两个 Debug
值。一个全球,一个成员 Box
class.
这是两个不同的值,因为 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
}