【问题标题】:C++ object reference returns different values [closed]C ++对象引用返回不同的值[关闭]
【发布时间】:2019-12-21 11:49:08
【问题描述】:

我使用 Arduino IDE 并为颜色管理编写了一些类:Fader 和 ColorManager。如果使用 ColorManager 对象初始化推子,我会根据访问位置获得不同的颜色值。如果我尝试访问构造函数中的对象引用,我会得到正确的值。如果我在其他一些类方法中做同样的事情,我会得到错误的值。

我做错了什么还是这是一个 g++/C++ 错误?

主要:

#include <ColorManager.h>

#define BLUE_PIN 3
#define GREEN_PIN 5
#define RED_PIN 6

void setup() {
  Serial.begin(9600);
  while(!Serial) {}
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  pinMode(7,INPUT_PULLUP);
}

#define GAMMA 1.0f
#define HUE_RED 1.0f
#define HUE_GREEN 1.0f
#define HUE_BLUE 1.0f

ColorManager to_rgb(uint8_t r,uint8_t g, uint8_t b) {
  ColorManager color = ColorManager(r,g,b);
  return color;
}

ColorManager stColor = ColorManager((uint8_t)255,0,0);

void loop() {
  ColorManager& curColor = stColor;
  Fader f = Fader(ColorManager((uint8_t) 255,0,0),ColorManager((uint8_t) 0,255,0));
  curColor = f.doStep();
  curColor.getRed(); // This call changes the output
  while(1) {}
}

标题

#ifndef ColorManager_H
#define ColorManager_H
#include <math.h>
#include <stdint.h>
class ColorManager {
public:
    ColorManager(uint8_t r,uint8_t g, uint8_t b);
    ColorManager(float r, float g, float b);
    ColorManager(float red = 1.0, float green = 0.0, float blue = 0.0, float gammaCorrection = 1.0, float hueRed = 1.0, float hueGreen = 1.0, float hueBlue = 1.0, uint16_t m = 255);
    uint16_t getGreen() const;
    uint16_t getBlue() const;
    uint16_t getRed() const;
    uint16_t getBrightness() const;
    ColorManager operator* (float b);
    void setGammaCorrection(float gamma);
    void setHueCorrection(float r, float g, float b);
    void setMax(uint16_t m);
    uint16_t getMax() const;
    float red;
    float green;
    float blue;

protected:
    const ColorManager* norm();
private:

    float hueRed;
    float hueGreen;
    float hueBlue;
    float gammaCorrection;
    uint16_t m;
};

class Fader {
public:
    Fader(const ColorManager& a, const ColorManager& b);
    const ColorManager& doStep();
    void setInterpolation(uint8_t (*stepper)(uint8_t));
    void setPhaseShift(int shift);
    bool fadeFinished();
    uint8_t getPhase() const;
    int getShift() const;
    void reset();
    float ramp_r;
    float ramp_b;
    float ramp_g;
protected:
    static uint8_t defaultIntp(uint8_t step);
private:
    uint8_t phase;
    int shift;
    bool started;
    uint8_t (*stepper)(uint8_t);
    const ColorManager& startColor;
    const ColorManager& endColor;
    ColorManager currentColor;
};
#endif

颜色管理器.cpp

#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <Arduino.h>
#include <ColorManager.h>
#define MAX_OUTPUT 255
const ColorManager* ColorManager::norm() {
    this->red /= (float) 255;
    this->green /= (float) 255;
    this->blue /= (float) 255;
    return this;
}

ColorManager::ColorManager(uint8_t r, uint8_t g, uint8_t b) : red(r),green(g),blue(b),m(255) {
    this->norm();
    setGammaCorrection(1);
    setHueCorrection(1,1,1);
}

ColorManager::ColorManager(float r, float g, float b) : red(r),green(g),blue(b),m(255) {
    setGammaCorrection(1);
    setHueCorrection(1,1,1);
}
ColorManager::ColorManager(float red, float green, float blue, float gammaCorrection, float hueRed, float hueGreen, float hueBlue,uint16_t m) : red(red),green(green),blue(blue),gammaCorrection(gammaCorrection),hueRed(hueRed),hueGreen(hueGreen),hueBlue(hueBlue),m(m) {}

void ColorManager::setGammaCorrection(float gamma) {
    this->gammaCorrection = gamma;
}

void ColorManager::setHueCorrection(float r, float g, float b) {
    this->hueRed = r;
    this->hueGreen = g;
    this->hueBlue = b;
}

void ColorManager::setMax(uint16_t m) {
    this->m = m;
}

uint16_t ColorManager::getMax() const {
    return this->m;
}

uint16_t ColorManager::getRed() const {
    float r = this->red;
    r = pow(r,this->gammaCorrection) * this->m * this->hueRed;
    return round(r);
}

uint16_t ColorManager::getGreen() const {
    float green = this->green;
    green = pow(green, this->gammaCorrection) * this->m * this->hueGreen;
    return round(green);
}

uint16_t ColorManager::getBlue() const {
    float blue = this->blue;
    blue = pow(blue,this->gammaCorrection) * this->m * this->hueBlue;
    return round(blue);
}
uint16_t ColorManager::getBrightness() const {
    return sqrt(pow(red * this->hueRed,2)+pow(green*this->hueGreen,2)+pow(blue*this->hueBlue,2)) * this->m;
}

ColorManager ColorManager::operator*(float b) {
    return ColorManager(this->red * b, this->green * b, this->blue * b, this->gammaCorrection, this->hueRed, this->hueGreen, this->hueBlue);
}

Fader.cpp

#include <ColorManager.h>
#include <Arduino.h>
#include <math.h>
Fader::Fader(const ColorManager& a, const ColorManager& b) : startColor(a),endColor(b),currentColor(a),phase(0),stepper(&Fader::defaultIntp),shift(0),started(false) {
    this->ramp_r = (b.red - a.red)/100;
    this->ramp_g = (b.green - a.green)/100;
    this->ramp_b = (b.blue - a.blue)/100;
    Serial.println(a.red);
}

uint8_t Fader::defaultIntp(uint8_t step) {
    return step;
}

void Fader::setInterpolation(uint8_t (*stepper)(uint8_t)) {
    this->stepper = stepper;
}

void Fader::setPhaseShift(int shift) {
    this->shift = shift;
}

bool Fader::fadeFinished() {
    return this->stepper(this->phase) == 100;
}

const ColorManager& Fader::doStep() {
    uint8_t mappedPhase = this->stepper(this->phase + this->shift);
    if (mappedPhase < 100) {
        this->phase = ++phase;
    }
    Serial.println(this->startColor.red);
    this->currentColor.red = this->startColor.red + this->ramp_r * mappedPhase;
    this->currentColor.green = this->startColor.green + this->ramp_g * mappedPhase;
    this->currentColor.blue = this->startColor.blue + this->ramp_b * mappedPhase;
    return this->currentColor;
}

uint8_t Fader::getPhase() const {   
    return this->phase;
}

int Fader::getShift() const {
    return this->shift;
}

void Fader::reset() {
    this->phase = 0;
    this->currentColor = this->startColor;
}

【问题讨论】:

  • 请发帖minimal reproducible example。 (这不是编译器错误,这是您的问题。)
  • First Rule of Programming。请告诉我们Fader类的定义。
  • @molbdnilo 您知道原因,那么如果您提出一些建设性的批评并可以解释问题,那就太好了。否则,说“这是你的错”是不可持续的。
  • @Sebi2020 我们不知道原因,因为您没有提供minimal reproducible example。但我 99.9% 确信编译器在数百万 C++ 开发人员每天使用的用例中没有错。
  • A 无法使用 g++ 重现错误。看起来它只发生在 Arduino IDE 中。

标签: c++ class oop arduino


【解决方案1】:

这一行导致悬空引用:

Fader f = Fader(ColorManager((uint8_t) 255,0,0),ColorManager((uint8_t) 0,255,0));

参数是临时的,但Fader 存储了对参数的引用

const ColorManager& startColor;
const ColorManager& endColor;

因此,在执行该行之后,这些引用引用了不再存在的临时对象,当您尝试在 doStep 中使用它们时会导致未定义的行为。

在考虑为类提供引用成员时,您应该始终注意这是一个陷阱。另一个这样的陷阱是该类将不可分配或移动,因为您不能“重新定位”引用

要解决此问题,您可以将成员设为 ColorManager(不是 const 也不是引用)。或者您可以将f 的初始化更改为不使用临时对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多