【问题标题】:Multiple layer of inheritance C++多层继承 C++
【发布时间】:2012-03-04 04:44:31
【问题描述】:

我有一个包含纯虚函数(如加载和卸载)的基础资源。然后我有一个从这个类继承的类并且是 AudioResource 并且具有虚拟功能,也就是播放和停止。然后我在这个类中固有并有一个名为 BassAResource 的类。

假设我返回了 Resource* 类型,然后我想将其类型转换为 AudioResource 并调用加载函数,并让它实际处理的类来处理它,但我一直遇到问题,说它是纯的AudioResource 中的虚函数 =s

class Resource
{
    public:
        Resource();
        Resource(std::string filename,unsigned int scope, RESOURCE_TYPE type);
        virtual ~Resource();
        virtual void load() = 0;
        virtual void unload() = 0;


class AudioResource : public Resource
{
    public:
        AudioResource(std::string filename, unsigned int scope, RESOURCE_TYPE type, AUDIO_T Atype);
        virtual void load() = 0;
        virtual void unload() = 0;
        virtual void play() = 0;
        virtual void pause() = 0;
        virtual void stop() = 0;

class BASSAResource : public AudioResource
{
    public:
        ~BASSAResource();
        virtual void load();
        virtual void unload();
        virtual void play();
        virtual void pause();
        virtual void stop();

【问题讨论】:

  • 您需要更好的源代码摘录。您包含的类定义不完整(所有 3 个都缺少右花括号和分号),并且您没有包含任何试图调用 load 函数的代码。

标签: c++ inheritance virtual


【解决方案1】:

您无法构造“AudioResource”,因为它具有未定义的方法。我假设您要返回一个已转换为资源指针的“BASSAResource”。让我伪代码,看看我是否明白你的意思

Resource *myFunc() {
   BASSAResource *resource = new BASSAResource();
   return (Resource*)resource;
}

void myMain() {
   Resource *resource = myFunc();
   AudioResource *audio = (AudioResource*) resource;
   audio->load();
}

这应该可以正常工作 - 实际上为什么要转换为 AudioResource,因为 load 被定义为 Resource 类中的抽象方法。但是,如果您想“玩”,则需要此演员表。同样,您不能使用“new AudioResource()”进行构造,因为您有一个必须首先实现的抽象方法。

另外,要非常小心地将所有析构函数设为虚拟。您的 ~BASSAResource 不是虚拟的,这会给您带来麻烦。

【讨论】:

  • 在类上没有虚拟析构函数并没有固有的问题,并且建议某人应该始终拥有一个而不解释它何时重要是没有用的。虚拟析构函数仅在您的类(或某些未来的子类)将在析构函数中完成重要工作时才有用,即使派生类正在被破坏,也需要发生这种工作。这经常发生,但并非总是如此。
  • 总是将析构函数声明为虚拟的。如果您不这样做,它们将不会按预期运行。这会导致静默内存泄漏和清理问题。没有正当理由不这样做。
  • @AndrewKhosravian:通过基类指针删除对象时需要虚拟析构函数(例如Base*base=new Derived; delete base;。但是,在继承场景中强制转换为基类指针非常常见,如果您有虚拟方法,您可能还应该定义一个虚拟析构函数。
  • @Kieveli:显然有理由不定义虚拟析构函数,否则这不是一个选项(或者至少是默认行为)。不添加虚拟析构函数的一个关键原因是定义 POD 类型。请注意,许多标准库类型没有虚拟析构函数,包括std::stringstd::vector 和其他容器。
  • 感谢您的措辞比我制作的安德烈的烂摊子更清楚。
【解决方案2】:

虚拟继承仅适用于指针(您必须引用对象,而不是类型)。相反,将其转换为 AudioResource* 类型并将其视为指针(或使用智能指针)。

【讨论】:

  • 我正在这样做:AudioResource* temp = (AudioResource*)(AudioManager::getInstance()->get("Song1.mp3")); get 函数返回 Resource 的类型,然后我将类型转换为 AudioResource 我不确定这是否是您的意思?
  • 您在哪一行出现错误?因为这看起来像是一条有效的线。
猜你喜欢
  • 1970-01-01
  • 2011-06-16
  • 2014-03-04
  • 2014-12-22
  • 1970-01-01
  • 2011-02-12
  • 2017-03-31
  • 2016-11-03
  • 1970-01-01
相关资源
最近更新 更多