0

这是我第一次将我的库功能拆分为多个类。我不确定如何根据类实例化我的对象。即使类在同一个 .h 文件中,我是否需要实例化类对象才能访问这些类方法和变量?我收到第 30 行的错误“不允许不完整类型”。

我的代码:

/*
File: sensor.h

Header file for phSensor Library.
*/

#ifndef SENSOR_H
#define SENSOR_H

#include "mbed.h"
#include "cfExtensions.h"
#include "msExtensions.h"

#include <string>

class phSensor;
class ecSensor;
class tempSensor;

class sensor
{
public:
    sensor(); //Default sensor constructor
    sensor(cfExtensions &cfExt, msExtensions &msExt);

private:
    cfExtensions &_cfExt;
    msExtensions &_msExt;

    phSensor     ph;  // Line 30, gets error "incomplete type is not allowed"
    ecSensor     ec;
    tempSensor   temp;

    string _phCurrentPhValue;
    string _phMaxValue;
    string _phMinValue;

};

class phSensor
    : public sensor
{
public:
    phSensor();

    void outputPhMaxValue();

private:
    float _getCurrentPhValue();
    float _getPhMaxValue();
    float _getPhMinValue();

    void _setPhMaxValue();
    void _setPhMinValue();

    void _calibratePhSensor();

    Ticker getPhMax;
    Ticker getPhMin;
};

class ecSensor
    : public sensor
{
public:
    ecSensor();
};

class tempSensor
    : public sensor
{
public:
    tempSensor();

};

#endif
4

4 回答 4

2

在您的情况下,您只能声明对不完整类型的指针或引用

phSensor     ph;
ecSensor     ec;
tempSensor   temp;

所有这些都会出错,如果sensor不知道所有成员的布局,就无法定义布局。

此外,对象不可能包含其自己的类的子对象,但这就是您要尝试做的事情 -既继承phSensor又是. 很可能您需要这些作为指针。ecSensorsensorsensor

phSensor     *ph;
ecSensor     *ec;
tempSensor   *temp;
于 2012-12-05T13:39:26.633 回答
2

其他人已经评论了声明的问题phSensor ph;

我要评论你的设计。

关于你的class sensor
第一关,你为什么要这样做?

您在面向对象中学习的第一件事是关于继承,例如一个Vehicle类,其中Car,TruckBicycle所有都是该基本车辆类的子类。很好,很简单,但经常出错。最终,您需要摒弃对面向对象编程的幼稚看法。

恰当的例子:仅仅因为 pH 传感器、电导率传感器和温度传感器都是某种类型的传感器,并不一定意味着创建Sensor基类是一个好主意。所有传感器共有的共同元素是什么?如果没有,那么拥有那个sensor基类可能不是一个好主意。

做一件事并做好
你的sensor班级正在做两件事。它是其他传感器类的基类它是三种传感器的集合。这是两个非常不同的东西,所以这些不同的行为应该属于两个非常不同的类。如果您将该类分为两个类,sensor作为基类(如果需要;见上文)和一个multisensor包含 pH 传感器、电导率传感器和温度传感器的类,那么您的直接问题就会消失。没有必要让这个multisensor类继承自sensor,甚至从phsensoretc 继承。这个新类将包含多个传感器。组合通常是比继承更好的途径。

关于类sensor构造函数
您有两个作为引用的数据成员。引用只能由构造函数设置,并且只能在初始化列表中。我可以看到非默认构造函数做了什么。你的默认构造函数是做什么的?您的派生类只有默认构造函数,这表明它们正在调用sensor类的默认构造函数。这有意义吗?摆脱那些默认构造函数可能会更好。在 C++03 中执行此操作的标准方法是将默认构造函数声明为私有但从不提供实现。C++11 中有一个更好的选择,就是将构造函数声明为已删除。

于 2012-12-05T14:35:06.887 回答
1

您声明了 phSensor 类,因此类型名称是已知的。尽管如此,此时编译器对该类的成员或方法一无所知,因此它无法知道类型的大小。只要类只被声明而不被定义,你就只能对它使用指针或引用。

另外:如果您仔细查看班级布局,这将无法正常工作。假设您实例化 phSensor。phSensor 扩展了传感器,因此也初始化了传感器的所有成员。其中一个成员又是一个 phSensor,它是从传感器派生的,它持有另一个继承传感器的 phSensor,依此类推。你看,这个实例化永远不会结束并耗尽所有内存。

于 2012-12-05T13:39:41.847 回答
1

您不应该在同一个文件中声明这些类。如果你这样做,模块化代码的想法是没有意义的。

于 2012-12-05T13:40:26.047 回答