【问题标题】:Inheritance in C++C++ 中的继承
【发布时间】:2010-09-19 05:14:06
【问题描述】:

这是我的问题:我在 .h 文件中定义了一个虚拟方法,我想在从基类继承的类中调用它。可悲的是,派生类中的方法没有被调用。有没有更好的方法来实现我正在尝试做的事情?

#ifndef ofxBASE_SND_OBJ
#define ofxBASE_SND_OBJ

#include "ofConstants.h"

class ofxBaseSndObj {

public:

    virtual string getType(){}

    string key;

};

#endif

这是我的嗡嗡声课程

#ifndef OFXSO_BUZZ
#define OFXSO_BUZZ

#include "ofxBaseSndObj.h"

class ofxSOBuzz : public ofxBaseSndObj
{
public:
    string getType();
};

#endif

ofxSOBuzz.cpp

string ofxSOBuzz::getType()
{
    string s = string("ofxSOBuzz");
    printf(" ********* returning string type %s", s.c_str()); // doesn't get called!
    return s;
}

然后在另一个班级我尝试这样称呼它:

string ofxSndObj::createFilter(ofxBaseSndObj obj)
{
    string str = obj.getType();
    if(str.compare("ofxSOBuzz") == 0)
    {
        printf(" all is well ");
    }
}

在上面的方法中,我需要能够传入多种对象中的一种,这些对象都扩展了 ofxBaseSndObj 对象。任何建议或指示将不胜感激。谢谢!

【问题讨论】:

  • 据我所知,您的标头(您在其中定义 ofxBaseSndObj)将无法编译,因为您有一个没有返回语句的非 void 返回类型的函数。你是怎么做到的?
  • 是时候接受一个正确的答案了!!单击您认为最能回答问题的答案旁边的复选标记之一。

标签: c++ oop inheritance


【解决方案1】:

改变这一行:

string ofxSndObj::createFilter(ofxBaseSndObj obj)

string ofxSndObj::createFilter(ofxBaseSndObj& obj)

您正在做的是按值传递(传递副本)。

这意味着您正在将对象复制到函数中。因为函数不知道你实际传递的是什么类型,所以它只传递函数声明中定义的类型,因此它会复制基类(这就是slicing 问题)。

解决办法是通过引用传递。

如果您不希望函数修改对象(也许这就是您按值传递的原因,因此它无法更改原始对象)然后传递一个 const 引用。

class ofxBaseSndObj
{
    public:
        virtual string getType()  const;
        // If the method does not change the object mark it const

        string key;

};

string ofxSndObj::createFilter(ofxBaseSndObj const& obj)
{
    // allowed to call this if getType() is a const
    string str = obj.getType();

    if(str.compare("ofxSOBuzz") == 0)
    {
        printf(" all is well ");
    }
}

【讨论】:

    【解决方案2】:

    您需要将实例作为对象的指针(或引用)传递给createFilter。您是passing by value,这会导致编译器将您用作参数的派生对象复制到基类的实例中。当它这样做时,您会失去它最初是派生类型的事实。

    您的代码实际上不应编译,因为 ofxBaseSndObj::getType 的声明不返回任何内容。你的意思是这是一个抽象方法还是返回一个空字符串?

    如果您将其设为抽象方法,那么编译器会抱怨尝试在您的 ofxSndObj::createFilter 方法中实例化抽象类。

    【讨论】:

    • 是的,你是对的,奇怪。它不应该编译......奇怪。我在gcc4.2上,不知道有没有其他人遇到过这个?
    【解决方案3】:

    这个问题在 C++ 中称为"slicing"

    【讨论】:

      【解决方案4】:

      将复制构造函数和 operator= 设为私有是防止此错误再次发生的有效方法。

      例如:

      class ofxBaseSndObj {
      public:
          virtual string getType(){}
          string key;
      
      private:
          ofxBaseSndObj(const ofxBaseSndObj& rhs);
          ofxBaseSndObj& operator=(const ofxBaseSndObj& rhs);
      };
      

      如果没有其他充分的理由,您应该使用 C++ 内置的 RTTI。然后,您可以使用 typeid 运算符。如果默认情况下未打开,请查看您的编译器文档以将其打开。

      【讨论】:

      • 是的,我将重新设计以仅使用指针和 RTTI。我想避免通过引用传递(长话短说,API 有一个奇怪的用户群),但我认为这是它工作的唯一方式,也是最有意义的方式。谢谢!
      【解决方案5】:

      其他人已经解决了切片问题。然后你问好吧,让我说,我知道我需要做一些事情来确定基本类型,但是有没有比进行枚举查找来确定继承对象的类型更优雅的方法? p>

      查询和切换对象的类型是一个糟糕的设计,它错过了 OO 方法的要点。

      代替

      string ofxSndObj::createFilter(ofxBaseSndObj& obj)
      {
          string str = obj.getType();
          if(str.compare("ofxSOBuzz") == 0)
          {
              // do ofxSOBuzz - specific thing
          }
          else if(str.compare("some other derived class") == 0)
          {
              // do stuff for other derived classes
          }
             // etc...
      }
      

      把有趣的行为变成虚函数:

      class ofxBaseSndObj {
      
      public:
          // get rid of getType()
          virtual void HelpCreateFilter() = 0;
      };
      
      
      string ofxSndObj::createFilter(ofxBaseSndObj& obj)
      {
          // Let the derived class do it's own specialized work.
          // This function doesn't need to know what it is.
          obj.HelpCreateFilter();
          // rest of filter creation
      }
      

      为什么这比原来的版本好?因为ofxSndObj::createFilter如果将来的ofxBaseSndObj派生类添加到系统中不需要修改。您的版本需要为每个新的派生类扩展。如果不清楚,请尝试发布更多代码 - 我无法从您的代码或类名中判断这些函数应该做什么。

      【讨论】:

      • 他走了 - 带着他的问题。
      【解决方案6】:

      您可以使用 dynamic_cast 或 type_id

      【讨论】:

        猜你喜欢
        • 2015-04-19
        • 2012-10-30
        • 2013-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-13
        • 2023-04-06
        相关资源
        最近更新 更多