Вызов методов класса, производного от абстрактного класса [C ++] - PullRequest
2 голосов
/ 19 февраля 2011

Вы должны простить меня, если это действительно простой вопрос;Я долгое время не использовал С ++ так много, поэтому я забыл, как много это работает.

В любом случае, у меня есть базовый класс и пара производных классов, как это (супер упрощенно, носуть та же):

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];

Позже я заполняю этот массив экземплярами Derived1 и Derived2.Это работает с baseobjects[i] = &newDerived1 (где newDerived1 является экземпляром класса Derived1).Все в порядке.

То, что я не могу понять, это то, как позже выполнить итерацию в массиве baseobjects и вызывать SomeFunction для каждого экземпляра в списке , не зная явно, какой производный классЯ использую .Я сделал это в C #, и он работает нормально, но, очевидно, мой синтаксис C ++ выключен:

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

Это дает мне ошибку LNK2019 при попытке компиляции, очевидно, потому что он смотрит на Base класс для реализации и его там нет.Я предполагаю, что мне нужно использовать некоторые приемы указателя, чтобы заставить его взглянуть на правильный производный метод, но ничего из того, что я пробовал, пока не сработало.Есть предложения?

Ответы [ 4 ]

8 голосов
/ 19 февраля 2011

Ваш метод должен быть объявлен virtual. А в вашем случае, вероятно, pure 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
};

Edit:

Кроме того, вы указали ошибку ссылки:

Либо вы забыли = 0, либо вы звоните Base::SomeFunction() откуда-то.

Как указывает Томас Эдлесон , = 0 не означает, что ваша функция не имеет реализации: она может иметь ее, но требует, чтобы производные классы (пере) реализовали ее, чтобы она не была аннотация .

Если вас заинтересовала эта тема, предлагаю вам прочитать этот пост .

2 голосов
/ 19 февраля 2011

Если вы хотите переопределить метод, он должен быть виртуальным.

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;
    }
}
1 голос
/ 19 февраля 2011

Вы должны объявить функцию-член SomeFunction ()

  1. виртуальный
  2. аннотация

Итак, объявление для Base должно выглядеть так:

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

Вы можете опустить виртуальное ключевое слово в производных классах.

0 голосов
/ 19 февраля 2011

Чтобы немного проработать ответ ereOn, вам do необходимо объявить вашу функцию базового класса (т.е. ваше абстрактное определение), чтобы ваши производные классы могли ее переопределить. Однако он не пояснил, что кроме этого, то, что вы опубликовали, прекрасно (то есть вызовы функции, которую вы опубликовали, будут работать без изменений).

Также обратите внимание, что если вы хотите получить чисто абстрактное определение, вам следует добавить = 0 к объявлению функции следующим образом:

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

Это позволяет компилятору знать, что классы, производные от Base, должны предоставлять свою собственную реализацию SomeFunction.

...