【问题标题】:Hiding/Virtual Function Usage C++隐藏/虚拟函数使用 C++
【发布时间】:2012-08-25 20:28:19
【问题描述】:

这是一个我很长一段时间都无法找到解决方案的具体问题。我有这个代码:

#include <iostream>

using namespace std;

class Mammal
{
  public:
  Mammal() {cout << "Mammal Constructor\n";}
  virtual ~Mammal() {cout << "Mammal Destructor\n";}
  virtual void Run() {cout << "Mammal Ran One Space\n";}

  protected:
  int mammalDistance;
};

class Horse : public Mammal
{
    public:
    Horse() {cout << "Horse Constructor\n";}
    ~Horse() {cout << "Horse Destructor\n";}
    void Run() {cout << "Horse Ran One Space\n";}
    void Run(int distance) {horseDistance = distance;
                            cout << "Horse Ran " << horseDistance << " Spaces\n";}

    protected:
    int horseDistance;
};

int main()
{
    Mammal *pHorse = new Horse;
    pHorse->Run(5);
    delete pHorse;
    return 0;
}

现在,如果我使用 void Run(int horseDistance) 并将其移至 Mammal 中,则此代码有效,但我想知道是否有办法将其保留在马中而不保持隐藏。

编辑:我的意思是,如果我采用接受输入的函数并将其向上移动到 Mammal 中,而不是像现在这样将它放在 Horse 类中,它会按预期编译和工作。 是的,如果它可以在传入 horseDistance 时改变它的值,我希望它。 编辑:哦,我明白你的意思。我编辑了代码。

【问题讨论】:

  • 您能否进一步解释一下,我不确定您的意思。
  • 定义“作品”。你的意思是“编译”吗?
  • 你还想让run(int)引用horseDistance吗?如果是这样,您打算使用参数horseDistance 还是成员Horse::horseDistance

标签: c++ class function virtual


【解决方案1】:

你有两个选择。一个是跟踪您的指针是马的事实:

int main()
{
    Horse *pHorse = new Horse;
    pHorse->Run(5);
    delete pHorse;
    return 0;
}

另一种是在Mammal中声明一个虚函数:

virtual void Run(int mammalDistance) = 0;

如果马是唯一跑特定距离的东西,我会选择选项#1,否则选择选项#2。

【讨论】:

  • 您甚至可以添加一个默认实现:void Run(int d) { for(int x = 0; x &lt; d; ++x) Run(); }。但这取决于 OP 来考虑。
  • 选择这个答案是因为它让我可以在 Horse 中保留成员函数,并帮助我最大程度地理解为什么我无法做我最初想做的事情。不过,其他答案都是可能的解决方案。
【解决方案2】:
Mammal *pHorse = new Horse;
pHorse->Run(5);

不起作用,因为 Mammal 中没有签名为 void Run(int) 的成员函数。更准确地说:Horse 类中给出的函数 void Run(int) 不是 Mammal 中函数 void Run() 的覆盖,因为签名不同。

您应该考虑将void Run(int) 添加到 Mammal 接口,如果它是一个函数,更多子类将实现。

【讨论】:

    【解决方案3】:

    现在您知道 pHorse 是一匹马,但对于编译器来说,它就不同了。 唯一的方法是使用动态转换检查 pHorse 是否为马,然后将其转换为 Horse* 并转换 Run(5) 方法。

    Horse* pHorse2=dynamic_cast<Horse*>(pHorse);
    if(pHorse2!=NULL){
       pHorse2->Run(5);
    }else{
       pHorse->Run();
    }
    

    【讨论】:

      【解决方案4】:

      我认为您在这里寻找多态性。您所有派生的Mammals 只需实现getDistance()setDistance(),也可以实现getAnimal() 以提供名称。我认为在设计上还有一些改进的空间,但是你会通过这种方式掌握多态性的窍门。可能是这样的:

      #include <iostream>
      
      using namespace std;
      
      class Mammal
      {
      public:
        Mammal() {cout << "Mammal Constructor\n";}
        virtual ~Mammal() {cout << "Mammal Destructor\n";}
        virtual void Run() {cout << getAnimal() << " Ran " << getDistance() << " Space\n";}
        virtual void Run(int p_distance)
        {setDistance(p_distance);
          cout << getAnimal() << " Ran " << getDistance() << " Spaces\n";}
      
      protected:
        virtual void setDistance(int p_distance) {mammalDistance = p_distance;}
        virtual int getDistance() {return mammalDistance;}
        virtual string getAnimal() {return "Mammal";}
        int mammalDistance;
      };
      
      class Horse : public Mammal
      {
      public:
          Horse() {cout << "Horse Constructor\n";}
          ~Horse() {cout << "Horse Destructor\n";}
      protected:
          int horseDistance;
          virtual string getAnimal() {return "Horse";}
      };
      
      int main()
      {
          Mammal *pHorse = new Horse;
          pHorse->Run(5);
          delete pHorse;
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多