调用从抽象类派生的类的方法[C ++]

时间:2011-02-19 16:31:38

标签: c++ abstract-class

如果这是一个非常基本的问题,你将不得不原谅我;我很长一段时间没有使用过C ++,所以我忘记了很多它的工作原理。

无论如何,我有一个基类和一些像这样的派生类(超简单,但要点是相同的):

class Base
{
public:
   Base () { }
   int SomeFunction (int x, int y); // abstract definition
};

class Derived1 : public Base
{
public:
   Derived1() : Base() { }
   int SomeFunction (int x, int y)
   {
      // actual implementation
      return 4;
   }
};

class Derived2 : public Base
{
public:
   Derived2() : Base() { }
   int SomeFunction (int x, int y)
   {
      // actual implementation
      return 7;
   }
};

稍后在main我有一个Base个对象列表:

Base *baseobjects[10];

稍后我用Derived1Derived2的实例填充该数组。这适用于baseobjects[i] = &newDerived1(其中newDerived1Derived1类的实例)。这一切都很好。

我似乎无法弄清楚如何稍后遍历baseobjects数组并在列表中的每个实例上调用SomeFunction,而不明确知道我是哪个派生类使用。我在C#中完成了这个并且它工作正常,但显然我的C ++语法已关闭:

int result = baseobjects[i]->SomeFunction(a, b);

当我尝试编译时,这给了我一个LNK2019错误,显然是因为它正在查看实现的Base类,但它不存在。我假设我必须使用一些指针技巧来让它看看正确的派生方法,但我尝试过的任何东西都没有用。有什么建议吗?

4 个答案:

答案 0 :(得分:8)

您的方法应声明为virtual。在您的情况下,可能 virtual

class Base
{
public:
   Base () { }
   virtual int SomeFunction (int x, int y) = 0; // abstract definition
};

请注意,虽然这不是绝对必需的,但您也可以声明一个virtual析构函数。如果您通过基类的指针删除派生实例,请执行此操作。

class Base
{
public:
   //Base () {} // This is not required, the default provided constructor is similar.
   virtual ~Base() {} // virtual destructor.
   virtual int SomeFunction (int x, int y) = 0; // abstract definition
};

编辑:

另外,关于您发布的链接错误:

您忘记了= 0,要么是从某个地方拨打Base::SomeFunction()

正如 Thomas Edleson 指出的,= 0并不意味着你的函数没有实现:它可以有一个,但它只需要派生类(重新)实现它不是抽象

如果您对此主题感兴趣,建议您阅读this post

答案 1 :(得分:2)

如果要覆盖方法,则必须是虚拟的。

class Base
{
public:
   Base () { }
   virtual int SomeFunction (int x, int y); // abstract definition
}

第二件事是你的派生类没有扩展你的基类。

class Derived1 : public Base
{ 
 public:
    Derived1() : Base() { }
    int SomeFunction (int x, int y)
    {
        // actual implementation
        return 4;
    }
}

答案 2 :(得分:1)

您必须声明成员函数SomeFunction()

  1. 虚拟
  2. 抽象
  3. 所以Base的声明应如下所示:

    class Base
    {
    public:
        Base() { }
        virtual int SomeFunction(int x, int y) = 0;
    };
    

    您可以省略派生类中的虚拟关键字。

答案 3 :(得分:0)

为了稍微详细说明ereOn的答案,你需要声明你的基类函数(即:你的抽象定义),以便你的派生类能够覆盖它。他没有澄清的是,除此之外,你发布的内容很好(也就是说,你发布的函数的调用将在没有任何修改的情况下工作)。

另请注意,如果您正在使用纯抽象定义,则应将= 0附加到函数声明中,如下所示:

class Base
{
public:
   Base () { }
   virtual int SomeFunction (int x, int y) = 0; // pure abstract definition
};

这使编译器知道从Base派生的类必须提供自己的SomeFunction实现。