【问题标题】:C ++ virtual functionC++ 虚函数
【发布时间】:2013-11-03 21:46:30
【问题描述】:

C++ 大师。

我正在尝试在 C++ 中实现多态性。我想编写一个带有虚函数的基类,然后在子类中重新定义该函数。然后在我的驱动程序中演示动态绑定。但我就是无法让它工作。

我知道如何在 C# 中做到这一点,所以我想我可能在我的 C++ 代码中使用 C# 的语法时犯了一些语法错误,但这些错误对我来说一点也不明显。因此,如果您能纠正我的错误,我将不胜感激。

#ifndef POLYTEST_H
#define POLYTEST_H
class polyTest
{
 public:
  polyTest();

  virtual void type();

  virtual ~polyTest();
};
#endif

#include "polyTest.h"
#include <iostream>

using namespace std;

void polyTest::type()
{
 cout << "first gen";
}

#ifndef POLYCHILD_H
#define POLYCHILD_H

#include "polyTest.h"

using namespace std;

class polyChild: public polyTest
{
 public:
  void type();
};

#endif

#include "polyChild.h"
#include <iostream>

void polyChild::type() 
{
  cout << "second gen";
}

#include <iostream>
#include "polyChild.h"
#include "polyTest.h"
int main()
{
  polyTest * ptr1;
  polyTest * ptr2;

  ptr1 = new polyTest();
  ptr2 = new polyChild();

  ptr1 -> type();
  ptr2 -> type();
  return 0;
}

我意识到我没有实现构造函数或析构函数,因为这只是一个测试类,它们不需要做任何事情,编译器会提供一个默认的构造函数/析构函数。这就是我收到编译错误的原因吗?为什么会这样?

【问题讨论】:

  • Ptr1 等待一个 polyChild,你给他一个 polyTest。你可以说这是一种父母类型,但给他一个孩子。反过来是不可能的。
  • 请提供真实代码。由于各种原因,该代码不应编译。从您开始声明 polyTest 默认 ctor 但您尚未定义它。
  • 你没有描述你遇到的错误。 “我就是无法让它发挥作用”,这还不够好。
  • @Manu343726,你是对的,我的代码确实没有编译,你能指出这是为什么吗?我现在会发布我所有的代码
  • 显示的代码包含内存泄漏! C++ 不会在你之后清理!如果您想要自动清理,请使用 std::unique_ptr&lt;polyTest&gt; ptr1(new PolyTest());

标签: c++ polymorphism virtual-functions


【解决方案1】:

您的指针应该指向基本类型:

polyTest * ptr1;
polyTest * ptr2;

polyChild is-a polyTest,但polyTest 不是 polyChild

【讨论】:

  • 哇,我才意识到我犯了一个愚蠢的错误。谢谢,请问为什么我的代码还是不能编译?
  • @user2950788 您必须提供更多详细信息。还有其他错误,在其他 cmets 中指出。
  • 对不起,我忘记更新我帖子中的那部分了。我确实修复了指针,但它仍然无法编译。你知道为什么会这样吗?
【解决方案2】:

juanchopanza 对您的问题给出了正确答案:您可以将子类型的指针分配给父类型的指针,因为子类也是父类的类型。

派生对象是基类对象(作为其子类),因此可以由基类指针指向。但是基类对象不是派生类对象,因此不能分配给派生类指针。

我会打个比方:狗是动物,猫是动物。你不能说动物总是猫或狗。

在 C++ 中,运行时类型检查是通过 dynamic_cast 实现的,这允许您检查父类是否属于某种类型的子类(在我的类比中,这允许您检查 Animal 是否是 Cat)。编译时向下转换由 static_cast 实现,但此操作不执行类型检查。如果使用不当,可能会产生未定义的行为。

一般来说,向下转换的滥用表明接口设计不佳,除非您正在实现双重调度模式之类的东西,否则您不应该在程序中一直使用向下转换。

另一方面,请将您的类大写,这在大多数(如果不是所有)C++ 约定中都是相当标准的。我修复了您程序中的所有其他内容,它应该可以编译。

#include <iostream>

using namespace std;

class PolyTest
{
 public:
     virtual ~PolyTest() {} // your example had no body
     virtual void type();

};

void PolyTest::type()
{
 cout << "first gen";
}


class PolyChild: public PolyTest
{
public:
    void PolyChild::type();
};

void PolyChild::type()
{ 
    cout << "second gen"; 
}


int main()
{
    PolyTest* ptr1 = new PolyTest();
    PolyTest* ptr2 = new PolyChild();

    ptr1->type();
    ptr2->type();

    cout << std::endl;

    PolyChild* pChild1 = dynamic_cast<PolyChild*>(ptr1);
    if (pChild1)
        cout << "ptr1 is a PolyChild" << std::endl;
    else
        cout << "ptr1 is NOT a PolyChild" << std::endl;

    PolyChild* pChild2 = dynamic_cast<PolyChild*>(ptr2);
    if (pChild2)
        cout << "ptr2 is a PolyChild" << std::endl;
    else
        cout << "ptr2 is NOT a PolyChild" << std::endl;

    cin.ignore(1);
    return 0;
}

我还添加了一些代码来演示 dynamic_cast。同样,您不应该滥用它,因为滥用它意味着您没有正确设计界面。

【讨论】:

  • @user2950788 认真的吗? “您已经声明了 polyTest 默认 ctor,但尚未定义它。”,这是您获得的第一个 cmets 之一。
  • @juanchopanza 我认为他是 SO 和 C++ 的新手
  • @BlueTrin,非常感谢您的解释!!你是对的,我第一次使用 SO。你能解释一下为什么我的代码在我实现构造函数和析构函数之前无法编译吗?根据我的理解,如果我不实现构造函数和析构函数,编译器将为我提供绝对不执行任何操作的默认构造函数/析构函数。在这种情况下,我不需要 constr/destru 来做任何事情。所以我什至没有费心把它们写出来,但为什么会给我一个编译错误呢?
  • @user2950788 问题是您声明了一个默认构造函数。一旦你这样做了,你也必须定义它,而你没有这样做。这就是那个特定错误的根源。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2010-12-13
  • 2015-06-17
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多