【问题标题】:C++ inheritance and inherit variable inside the classC++继承和类内继承变量
【发布时间】:2015-12-09 15:55:27
【问题描述】:

假设我有一个名为 MasterClass 的类,它有一些具有公共继承的子类,如 ChildA、ChildB 等。

MasterClass 也有一个名为 MVar 的变量,它来自 AnimalClass 类型,显然还有一些子类,如 DogClass、CatClass 等

MasterClass 有 AnimalClass 但 ChildA 有 DogClass, ChildB 有 CatClass 等等。

如何创建一个仅在 master 中定义但通过其子级使用继承的函数:

ChildA ca; ca.emitSound();

并且 emitSound 只是调用类似 MVar.makeSound();

其中 emitSound 仅在 AnimalClass 上定义,其行为取决于孩子的类型。

我的问题是,emitSound 似乎总是调用 AnimalClass emitSound 而不是 DogClass emitSound。

显然,如果我在 ChildA、ChildB 等中定义了一个 emitSound,它可以正常工作,但我只是想让代码更小。

当然,我的现实生活问题比这个愚蠢的例子更复杂,但我认为问题几乎相同,即。 emitSound 可以是一个虚拟的,允许一些孩子覆盖它的行为等。

问候!

代码:

AnimalClass 
{
public:
      AnimalClass();
      virtual void makeSound(){ printf("nosound";}        
}


DogClass: public AnimalClass 
{
public:
      DogClass();
      void makeSound(){ printf("bufff";}        
}


MasterClass 
{
public:
      MasterClass();
      AnimalClass *ani;
      void emitSound(){ani->makeSound();}     
}

ChildAClass: public MasterClass
{           
public:
      ChildAClass(){ani=new DogClass();}
      DogClass *ani;
}

main()
{
    ChildAClass c;
    c.emitSound();
}

问题在于它打印的是“nosound”而不是“bufff”

【问题讨论】:

  • 在代码中编写这种关系可以让理解更简单
  • 你是对的!完成。
  • 你能写出一个带有 ideone.com 链接的工作示例吗?
  • 我刚刚用一个例子编辑了这个问题
  • 不,你没有。保证不编译的例子并不是真正的例子。

标签: c++ inheritance


【解决方案1】:
#include <iostream>

class Animal
{
public:
    virtual void sound()
    {
        std::cout << "Animal sound" << std::endl;
    }
    virtual ~Animal(){}
};
class Dog : public Animal
{
    void sound() //override
    {
        std::cout << "Dog sound" << std::endl;
    }
};

class Master
{
private:
    Animal *animal;
public:
    Master(Animal *a)
    {
        animal = a;
    }
    void emitSound()
    {
        animal->sound();
    }
    ~Master()
    {
        delete animal;
    }
};
class A : public Master
{
public:
    A(Dog *d) : Master(d){}
};

int main()
{
    A a(new Dog());
    a.emitSound();

    return 0;
}
OUTPUT: Dog sound

【讨论】:

  • 这可能是有道理的,但是由于我想在大量的类中这样做,并且它们将被第三方开发人员使用,一个理想的解决方案应该是 A 类可以生成 Dog 而不制作它以明确的方式。
【解决方案2】:

您提供的代码无法编译,因此很难确切知道您在真实代码中做错了什么。但看起来您的派生类中有一个 ani 指针,它隐藏了您的基类中的 ani 指针,因此基类中的指针永远不会被初始化。

您需要确保派生类的构造函数以某种方式初始化基类中的指针。例如,ChildAClass 可以有一个 DogClass 的实例并传递一个对 MasterClass 构造函数的引用。

#include <cstdio>

class AnimalClass 
{
public:
    virtual void makeSound(){ printf("nosound");}        
};

class DogClass: public AnimalClass 
{
public:
    void makeSound() override { printf("bufff");}        
};

class MasterClass 
{
    AnimalClass *ani;
public:
    MasterClass(AnimalClass& animal) : ani(&animal) {}
    void emitSound(){ani->makeSound();}     
};

class ChildAClass: public MasterClass
{      
    DogClass dog;
public:
    ChildAClass() : MasterClass(dog){}
};

int main()
{
    ChildAClass c;
    c.emitSound();
}

Live demo.

【讨论】:

  • 谢谢你我的代码不是一个有效的代码它只是暴露问题的一种快速愚蠢的方法。
  • @FrankEscobar 好吧,我们仍然不确定你真正的问题是什么。
  • 我写了一个解释...这是一个可能的解决方案。
  • @luk32 你可能是对的,但你在推测 OPs 代码的真正样子。
  • 不,我没有,至少我相信。他的例子在语法意义上并不完整。我认为在语义上没有什么可以解释的。 IE。您可以输入缺少的包含和括号,它会起作用。我认为你不需要任何逻辑。预期的行为也很清楚。但是我还没做=D。我很可能和你做了同样的假设。你写了一个可能的解决方案,我写了对原始行为的解释。
【解决方案3】:

发生的事情是AnimalClass::makeSound 被调用。这是因为在子类中您在ChildAClass 中有两个成员ani,即:ChildAClass::aniMasterClass::ani。第一个遮住了后者,但它仍然存在。

现在,即使您通过ChildAClass 调用emitSound,所调用的也是MasterClass::emitSound。所以你需要从这个角度来看事情。从那里你从AnimalClass 指针而不是DogClass 调用makeSound,因为AnimalClass::makeSound 对派生类一无所知。换句话说,成员不会被“虚拟化”。

你应该做的是在基类中拥有一个AnimalType*(或引用)类型的成员ani,并在派生类中正确初始化它。

【讨论】:

    猜你喜欢
    • 2013-04-19
    • 2023-02-09
    • 2013-02-11
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 2014-01-18
    • 2013-08-16
    • 2017-09-05
    相关资源
    最近更新 更多