【问题标题】:How can I use a void* argument in C++ for multiple object types?如何在 C++ 中为多种对象类型使用 void* 参数?
【发布时间】:2013-05-18 01:14:57
【问题描述】:

简而言之,我创建了多个类来表示来自不同设备(实际上是相机)的数据。它们在幕后都有不同的行为,但从外部看,它们的交互是完全相同的。我正在尝试编写一个实用程序函数,它可以与任一类或我编写的任何其他类一起使用,只要交互是相同的。我对 C++ 很陌生,如果我的术语不完全正确,请耐心等待。

假设我对每个相机都有这些定义。

class CamDataA
{
int getImageStart() {return ptrToStart;)
    int getImageSize() {return imageSizeVariable;)
}; 

class CamDataB
{
int getImageStart() {return ptrToStart;)
    int getImageSize() {return width*height*channels;)
}; 

我想要另一个单独的类,可以与任一类互换使用

class imageUtils
{
    //constructors/destructors

    int reportSize( void* camData)
    {
        cout << camData->getImageSize();
    }

}; 

但是我在编译时得到的错误是:

error: ‘void*’ is not a pointer-to-object type

这甚至可能吗?

【问题讨论】:

    标签: c++ void void-pointers


    【解决方案1】:

    void * 是一个无类型指针。要通过指针调用对象的方法,指针必须是适当的类型。如果您知道它指向什么对象,则可以将 void * 显式转换为 CamDataA*CamDataB*,但这不是您想要的(您事先不知道对象的类型)。

    在你的情况下,使用虚拟方法很好。

    1) 定义一个接口。 IE。定义一组没有实现的方法。

    class CamDataBase {
      public:
        virtual int getImageStart() = 0;  // "=0" means abstract methods - MUST be 
        virtual int getImageSize() = 0;   // overriden in descendants
    };
    

    关键字virtual 表示该方法可以在后代类中覆盖。这意味着如果我们有一个指针,比如CamDataBase* p,并且指针指向某个后代类,例如p = new CamDataA(),如果我们写成p-&gt;getImageStart(),那么将会有一个对应于真实(当前)对象类型(CamDataA::getImageStart())的方法调用,而不是CamDataBase::getImageStart(),尽管p是一个指向@987654333的指针@。

    2) 现在定义几个接口的实现。与父类中的虚拟方法具有相同签名的方法覆盖它们。

    class CamDataA: public CamDataBase {
      int getImageStart() {return ptrToStart;)
      int getImageSize() {return imageSizeVariable;)
    }; 
    class CamDataB: public CamDataBase {
      int getImageStart() {return ptrToStart;)
      int getImageSize() {return width*height*channels;)
    }; 
    

    3) 现在定义一个函数,该函数接受指向CamDataBase 或其任何后代的指针:

    void reportSize(CamDataBase* camData) // using the base class
    {
       // type of the object and the appropriate method 
       // are determined at run-time because getImageSize() is virtual
       std::cout << camData->getImageSize();
    }
    

    这里有几个例子:

    CamDataA A;
    CamDataB B;
    reportSize(&A); // CamDataA::getImageSize() is called
    reportSize(&B); // CamDataB::getImageSize() is called
    
    CamDataBase *p = &A;
    reportSize(p); // CamDataA::getImageSize() is called
    
    // and even if we cast pointer to CamDataA* to a pointer to CamDataB*:
    reportSize((CamDataB*)&A); // CamDataA::getImageSize() is called
    

    我希望你能在网上搜索所有对你来说陌生的词。 :)

    【讨论】:

    • 你的回答是正确的,但我建议你编辑它并向他解释你做了什么以及为什么......我认为他不了解 OO,这是他在这里遇到的最大问题 :)
    • 同意,我可以按照代码进行操作,但仍然不知道您具体做了什么以及为什么。谢谢!
    • 谢谢,我会编辑答案。我只是希望“虚拟”和“覆盖”这两个词能够指导他开始学习 OOP :) 不确定这里是否适合详细介绍多态性这样一个描述良好的主题。
    【解决方案2】:

    似乎第二个函数是小写的,而您将其定义为大写,并且您没有将其转换为特定对象。 ((CamDataA*)camData)->getImageSize...

    然而,这不是在 C++ 中执行此操作的方法,我建议您阅读更多有关面向对象的内容...因为进行强制转换和使用 void* 是非常类似于 C 的语法。

    使用面向对象,您可以进行类型检查(因为您可以将任何内容传递给 void*),它们为您的程序提供了更多的结构和清晰度。 C ++(和其他面向对象的语言)使用基类作为契约,表示该类型的所有对象都应该具有这些功能(方法),因此例如 bag 的基类定义了 PutItemInBag 的方法,然后定义了背包、手提箱、手提包等都继承自 bag 并且每个都可以有不同的 PutItemInBag 实现并以不同方式处理它,因为这样外部对象可以处理所有相同的包,而不必担心它是哪个对象,或者是否有新类型的对象系统。 这是通过虚拟方法完成的 - Virtual Method Overview

    然后你可以通过抽象的虚方法使基类抽象 (在 C++ 中使其 = 0)。这意味着此方法没有实现,您无法创建此类型的对象。这个类只是一个接口(或契约),从它继承的方法应该覆盖这个方法并给出自己的实现。 Abstract Classes

    你需要的是让两个类都有一个抽象基类并以这种方式处理它..

    class BaseCamData
    {
      virtual int getImageSize() = 0;
    };
    
    //then have both class inherit form it.
    class CamDataA : public BaseCamData
    {
      virtual int getImageSize () {return 50;/*imagesize*/}
    }
    
    class CamDataB : public BaseCamData
    {
      virtual int getImageSize () {return 70;/*imagesize*/}
    }
    
    
    
    
    int reportSize(BaseCamData* camData)
    {
         count << camData->getImageSize();
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2017-06-14
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 2018-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多