【问题标题】:Accessing another object's member [closed]访问另一个对象的成员 [关闭]
【发布时间】:2016-06-08 21:15:10
【问题描述】:

我是 C++ 的初学者,我想知道是否有一种访问另一个对象成员的好方法。

目前我正在使用它来访问成员:

&_HeatSensor->IsOverheating == true;
&_LeftLegSensor->IsStalled == true;
/*... many more similar ones but different names*/

其中 HeatSensor 或 LeftLegSensor 是对象的名称,IsOverheat 或 IsStalled 是对象中的布尔成员。

我想创建一个新的SensorOverLimit 类,并创建许多对象(例如:Left Leg、MotorTemperature... 等。

为了节省时间和重用代码,我希望能够传递一些可以引用在构造函数中创建的布尔成员的东西,然后通过引用或指针将位置保存为新 SensorOverLimit 对象中的成员。

SensorOverLimit.cpp

SensorOverLimit::SensorOverLimit(bool* SensorAddress)
{
    bool* Sensor = SensorAddress;
}

SensorOverLimit::Check()
{
    if  (SensorAddress == true)
    {
        somefunction();
    }
}

main.cpp:

SensorOverLimit Overheating = new SensorOverLimit(bool* &_HeatSensor->IsOverheating);
SensorOverLimit DamagedLeg = new SensorOverLimit(bool* &_LeftLegSensor->IsStalled);

这不起作用,有人知道如何让它起作用吗?

【问题讨论】:

  • 你是从哪本书上学的??
  • 另外,为什么要将“Disturb”作为指针传递?如果你只需要City::City(bool Disturb),问题就简单多了。
  • @kfsone ->(成员访问)在&(地址)之前。所以 _person 和 _animal 已经是指针,&name->IsWhatever 的结果是一个 bool* 类型的指针,指向 name->IsWhatever。
  • 为什么类的成员会作为参数传递给City构造函数?那里的关系为零;这是非常糟糕的面向对象设计。
  • @LilProgramma 如果您重写您的问题并澄清您正在为远程传感器编写代码,并将City 更改为Sensor,并将Person 更改为RemoteSensorA(或类似的东西),和animalRemoteSensorB,你可能会得到一个更好、有用和准确的答案。 尤其是,因为看起来您实际上是在尝试通过在传感器检测到干扰时创建新实例来保留一组主动“受干扰”传感器的实例。

标签: c++


【解决方案1】:

编辑:更改的问题,新的答案...

SensorOverLimit.h:

class SensorOverLimit
{
    bool* sensor;
public:
    SensorOverLimit(bool* sensorAddress);
    void check();
};

SensorOverLimit.cpp:

SensorOverLimit::SensorOverLimit(bool* sensorAddress)
    : sensor(sensorAddress)
{
}

void SensorOverLimit::check()
{
    if(*sensor)
    {
        somefunction();
    }
}

查看 Remy 的引用而不是指针的答案(bool& 而不是 bool*,您可以省略取消引用 (if(sensor))

main.cpp:

HeatSensor heatSensor;
LeftLegSensor leftLegSensor;
SensorOverLimit overHeating(&heatSensor.isOverheating);
SensorOverLimit leftLegDamaged(&leftLegSensor.isStalled);

int main(int, char*[])
{
    // ...
    return 0;
}

您可能已经注意到:我直接实例化了全局变量。这在嵌入式环境中通常更合适,至少更易于使用。

注意以下划线开头的标识符 - 这些标识符在许多情况下是保留的(C++ 标准,2.10):

每个包含双下划线 __ 或以下划线后跟大写字母的标识符都保留给实现以供任何使用。

每个以下划线开头的标识符都保留给实现,用作全局命名空间中的名称。

编辑 2:

我想出了一个完全不同的设计,颠倒你目前的设计:

class Sensor
{
public:
    Sensor()
            : isActive(false)
    { }
    virtual ~Sensor()
    { }

    void check()
    {
        if(getValue() != isActive)
        {
            isActive = !isActive;
            if(isActive)
            {
                someFunction();
            }
        }
    }
private:
    bool isActive;
    virtual bool getValue() = 0;
};

class HeatSensor : public Sensor
{
    virtual bool getValue()
    {
        bool isActive = false;
        // do what ever is necessary to detect overheat
        // e. g. read from ADC and compare against threshold
        return isActive;
    }
};

class LegSensor : public Sensor
{
    bool isSignal;
    virtual bool getValue()
    {
        // do what ever is necessary to detect stalled leg
        // e. g.: simply returning the value that has been set from
        // within an interrupt handler
        return isSignal;
    }
};

对我成员的名字不太满意,你可能会找到更好的...


但是,您对此设计的意图是什么?你要遍历每个城市,检查布尔指针吗?对我来说似乎是一个有问题的设计......

我为你推荐一个替代方案:

每个传感器都有一个 SensorOverLimit* 指针,您可以将其称为“控制器”或任何您认为合适的名称。然后为每个 Sensor 类添加函数:oveheating()stalling() 等。在这些函数中,您调用新定义的 SensorOverLimit 函数:disturb(int reason, Sensor* source)。您可以定义一个包含所有可能原因(例如过热、失速等)的枚举,而不是 int。

可能是这样的:

class Sensor;

class SensorOverLimit
{
    // appropriate members
public:
    enum Disturbance
    {
        Overheat,
        Stall,
    };

    SensorOverLimit() {}

    void disturb(Disturbance reason, Sensor* source)
    {
        someFunction();
    }
};

class Sensor
{
protected:
    SensorOverLimit* controller;
public:
    // ctor, getters, setters as needed
    Sensor(SensorOverLimit* aController) : controller(aController) {}
};
class HeatSensor : public Sensor
{
public:
    // ctor, getters, setters as needed
    HeatSensor(SensorOverLimit* aController) : Sensor(aController) {}
    void overheating()
    {
        if (controller)
            controller->disturb(SensorOverLimit::Overheat, this);
    }
};
class LegSensor : public Sensor
{
public:
    // ctor, getters, setters as needed
    LegSensor(SensorOverLimit* aController) : Sensor(aController) {}
    void stalling()
    {
        if (controller)
            controller->disturb(SensorOverLimit::Stall, this);
    }
};
SensorOverLimit controller;
HeatSensor heatSensor(&controller);
LegSensor leftLegSensor(&controller);

int main(int, char*[])
{
    // ...
    heatSensor.overheating();
    //...
    leftLegSensor.stalling();
    //...
    return 0;
}

优势:您可以将多个传感器关联到同一个控制器。

【讨论】:

  • City miami = new .... 确定?这不是 java。
  • 它适用于需要了解多个传感器状态的嵌入式系统,每个传感器都有自己的类,它只是用不同的名称进行了简化,以便于阅读。
  • 这确实解释了这个问题的可能意图,乍一看似乎是不相关类的奇怪混合。 +1 建议干扰的原因通知 City 对象(并找出问题的内容)。 @LilProgramma 最好使用真实名称,如 Sensor、Controller 或其他任何东西,以便人们了解您的需求。
  • @πάνταῥεῖ 已经在编辑了。假设我应该习惯在 IDE 中编写代码,而不是直接在这里...
  • @LilProgramma 这是一个重要的提示。下次你应该在你的问题中包含这个,我们大多数人都非常清楚嵌入式环境中的工作方式不同。我加入约翰 D,留下真实姓名。你的名字让我走向了一个完全不同的方向......
【解决方案2】:

您可以像这样使用bool* 指针:

class SensorOverLimit
{
public:
    bool* Sensor;
    SensorOverLimit(bool* SensorAddress);
    void Check();
};

...

SensorOverLimit::SensorOverLimit(bool* SensorAddress)
    : Sensor(SensorAddress)
{
    Check();
}

void SensorOverLimit::Check()
{
    if (*Sensor)
    {
         somefunction();
    }
}

SensorOverLimit *Overheating = new SensorOverLimit(&(_HeatSensor->IsOverheating));
SensorOverLimit *DamagedLeg = new SensorOverLimit(&(_LeftLegSensor->IsStalled));
...

那么你可以这样做:

_HeatSensor->IsOverheating = true;
... 
Overheating->Check();

_LeftLegSensor->IsStalled = true;
...
DamagedLeg->Check();

话虽如此,使用引用而不是指针会更安全:

class SensorOverLimit
{
public:
    bool& Sensor;
    SensorOverLimit(bool& SensorAddress);
    void Check();
};

...

SensorOverLimit::SensorOverLimit(bool& SensorAddress)
    : Sensor(SensorAddress)
{
    Check();
}

void SensorOverLimit::Check()
{
    if (Sensor)
    {
         somefunction();
    }
}

SensorOverLimit *Overheating = new SensorOverLimit(_HeatSensor->IsOverheating);
SensorOverLimit *DamagedLeg = new SensorOverLimit(_LeftLegSensor->IsStalled);
...

_HeatSensor->IsOverheating = true;
... 
Overheating->Check();

_LeftLegSensor->IsStalled = true;
...
DamagedLeg->Check();

【讨论】:

  • 正如我所发现的,他使用&_name->,因为name 是一个指针,他正在取消引用它以访问它的IsDead 成员,然后获取该成员的地址。
  • 应该想到自己的参考... +1。
【解决方案3】:

您不使用 getter 和 setter 来访问对象的成员是否有特殊原因?

如果您将所有对象都作为指针引用,您可能需要重新考虑这种做法。这个 StackOverflow 问题对 C++ 和指针的常见做法提供了一些见解:Why should I use a pointer rather than the object itself?

我认为您的问题的最佳答案实际上是让自己熟悉指针的概念。这个问题以及我之前提到的问题提供了一个很好的起点 - C++ Objects: When should I use pointer or reference。我认为需要注意的最好的事情之一是,如果您来自 Java 背景,那么指针和引用将隐藏在您的代码中。在 Java 中,每个对象都是一个指针,反之亦然。在 C++ 中,它们是分开的。

我认为你重用代码的愿望是值得称赞的,但在这种情况下,使用指针可能会导致未知错误!

我建议更改 City 类中的构造函数以实际使用对象,而不仅仅是它们的成员(例如,创建一个以人为参数的城市,而不是该人是生是死)。多练习一点面向对象编程,您可能会发现它比您最初的方法要容易得多!

【讨论】:

  • 我只是想知道是否有一种简单的可重复使用的方法来访问不同的成员位置。我更复杂的问题是将 Bool 转换为自定义数据类型,该数据类型还包含一个函数,每当 Bool 更改时,它将发送一个 QT 信号来告诉 City 对象它已更改状态。因此,我需要为 connect() 语句引用 IsDead。
  • @LilProgramma:这种糟糕的代码设计让你掉进了一个糟糕的兔子洞。我会让每个人或动物都包含一个指向他们所属城市的指针,如果人/动物死了,那么它可以直接通知城市。
  • @LilProgramma 澄清一下,您的 City 对象是否包含您所有的人和动物对象?现在看来,根据您正在尝试做的事情,您需要在对象设计上做一些工作。如果您的 Person 和 Animal 对象包含在城市中,那么做您想做的事情会容易得多。此外,Remy 的评论是另一种(可能更好)设计,具体取决于您希望对象的连接程度。
  • @tatertot 人和动物对象分别包含在单独的人和动物类中,具有自己的单独属性和方法。而 City 类包含以下城市:迈阿密、底特律……
  • @LilProgramma 我认为设计是你的问题。您的 City 类只是城市名称的列表?你如何让你的 City 类更有用,让每个城市都有一个名称、城市属性,然后为城市创建一个封闭类(State、Country、County、CityList 等)
猜你喜欢
  • 1970-01-01
  • 2014-07-30
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-07
  • 2017-05-07
  • 2012-01-13
  • 1970-01-01
相关资源
最近更新 更多