【问题标题】:How to have a pointer to class A OR class B in my class?如何在我的班级中有一个指向 A 类或 B 类的指针?
【发布时间】:2020-03-17 19:53:18
【问题描述】:

我创建了一个 C++ 类,它有一个公共成员,它是一个指向不相关类的指针。这里是:

class ADS_1x15 : public Sensors {
 public:
  ADS_1x15(uint8_t addr = 0x48, adsGain_t gain = GAIN_TWOTHIRDS, String = "");
  Adafruit_ADS1115* ads;

};

它是与 Adafruit ADS1115 ADC 执行不同操作的其他一些类的基类,因此成员 ads 可用于任何后代类。

有一个非常相似的 Adafruit ADC,称为 ADS1015,我希望我的课程能够使用这两个 ADC 中的任何一个。当然,Adafruit_ADS1015 与 Adafruit_ADS1115 是完全不同的对象。在我的基类中,我希望能够传入一个参数,该参数告诉类“包括指向 Adafruit_ADS1015 或 Adafruit_ADS1115 的指针,但无论使用哪一个,都要使指针的变量名称相同:@987654323 @"。这两个对象的所有方法都是相同的,所以一旦我将ads 指向正确的对象,我的类中的所有内容都会正常工作,无论使用哪个 ADS。

这可能吗?

【问题讨论】:

  • Adafruit_ADS1015Adafruit_ADS1115 是否共享一个公共基类?
  • 如果它们共享一个基类,您可以使用单个指针。如果没有,请考虑使用union,或者为清楚起见使用两个指针。
  • @tadman 我几乎每次都更喜欢std::variant 而不是union
  • @aschepler 如果可用 (C++17),是的,那也是!
  • 您可以使ADS_1x15 成为模板类,其中ads 的类型在模板参数中指定。然后ADS_1x15 的用户可以决定使用哪种类型。否则,就像你说的那样,由于Adafruit_ADS1015Adafruit_ADS1115 具有相同的方法,那么多态性对于这种情况是一个不错的选择,使它们派生自一个公共基类,然后使ads 成为该类型的指针。

标签: c++ class pointers


【解决方案1】:

如何在我的班级中有一个指向 A 类或 B 类的指针?

这可能吗?

是的。有可能的。您正在描述动态多态性。如果Adafruit_ADS1115Adafruit_ADS1015 共享一个基类B,那么B* 可以指向任一子类(的基子对象)。

还有另一种形式的动态多态性不需要继承:类型擦除。使用std::any 可以实现不受约束的类型擦除,它允许您的类包含任何类型的对象。并且有约束类型擦除允许使用标记联合 (std::variant) 实现的有限类型集。还有专门用于特定用例的类型擦除包装器,例如 std::function 用于存储任何类型的可调用对象。


请注意,动态多态性通常会涉及一些开销,这在您的情况下可能不是必需的。

另一种方法是静态多态性,可以通过使用模板来实现。例如,在这种情况下,您可以定义以下模板:

template<class Adafruit_ADS1x15>
struct ADS_1x15 : Sensors {
    Adafruit_ADS1x15* ads;

【讨论】:

  • 另外,如果现有类没有有用的通用接口类且无法修改,但您创建一个模仿它们的抽象接口类,以及一个继承新抽象的模板类接口并通过重定向到参数化的具体类来实现它们,那么您已经实现了自己的自定义类型擦除!
  • @eerorika,这似乎是要走的路(模板方法),但我不明白 MY 类的用户将如何传入标识两个 ADC 中的哪一个的参数正在使用。你能详细说明吗?谢谢!
  • @briansmith 他们在实例化模板时将其作为模板参数传递:ADS_1x15&lt;Adafruit_ADS1015&gt; 例如是模板的一个实例。类模板的实例是一个类。
  • 我最终为基类和我的后代类使用了类模板。我必须对如何做到这一点进行大量研究,但这是有教育意义的!谢谢@eeerorika 建议这种方法。
猜你喜欢
  • 2011-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-07
  • 2010-11-30
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多