Наследование и виртуальные методы - PullRequest
3 голосов
/ 25 января 2012

Я думаю, что у меня хорошее чувство, основанное на моих исследованиях, но я хотел бы получить подтверждение. Я узнал о наследовании и о том, как работают виртуальные методы.

В коде внизу я получаю результаты (код выше) при запуске main. Если я переключу метод printType на не виртуальный, я вместо этого получу распечатку «AbstractClass».

Насколько я понимаю, использование «виртуального» означает, что метод может быть перезаписан - и всегда выбирать «последнее переопределение» метода, в данном случае - в ExtensionClass. Мои вопросы:

1) Это ВСЕГДА случается? Или есть случаи, когда вы можете в итоге вызвать метод из AbstractClass (или других классов, если он наследуется несколько раз), даже если это виртуальный метод?

2) кажется, вы не можете создать экземпляр указателя класса, содержащего виртуальные методы. Это правда?

3) Я предполагаю, что в моих двух примерах нет ничего особенного, но я уверен только на 80%.

Большое спасибо за помощь, весь этот виртуальный метод сложно понять из чтения (именно поэтому я и создал фиктивный проект!).

after redefinition 
ImplementationClass
printing from virtual method in ImplementationClass

second set of examples 
ImplementationClass
printing from virtual method in ImplementationClass

#include <iostream>
using namespace std;

class AbstractClass{

public:
    virtual void printStuff() = 0;
    AbstractClass() {};
    ~AbstractClass() {};

    virtual void printType() { std::cout << "AbstractClass" << std::endl; }
    // void printType() { std::cout << "AbstractClass" << std::endl; }

};
class ImplementationClass : public AbstractClass {

public:
    void printStuff() { std::cout << "printing from virtual method in ImplementationClass" << std::endl;}
    void printType() { std::cout << "ImplementationClass" << std::endl; }
    void printStuffOnlyInDerived() {std::cout << "printing from NONvirtual method in ImplementationClass" << std::endl;}


    ImplementationClass() {};
    ~ImplementationClass() {};
};




int main () {

    AbstractClass * absClass;
    ImplementationClass * impClass= new ImplementationClass;

    absClass = impClass;

    printf("\nafter redefinition \n");  
    absClass->printType();
    absClass->printStuff();


    AbstractClass * absClassNonPtrImpClass = new ImplementationClass;

    printf("\n second set of examples \n"); 
    absClassNonPtrImpClass->printType();
    absClassNonPtrImpClass->printStuff();


    return 0;
}

Ответы [ 3 ]

3 голосов
/ 25 января 2012
  1. Да, вы можете явно указать метод базового класса и вызывать его даже через указатель на производный класс (pDerived->Base::virtualMethod() - это вызовет реализацию Base * 1005)*).Вы также можете вырезать объект производного класса и также потерять полиморфизм.

  2. Вы не можете создать объект класса с помощью abstract методов(объявлено с = 0), но вы, безусловно, можете создавать объекты классов с виртуальными методами, которые имеют реализации.

1 голос
/ 25 января 2012

1) Это ВСЕГДА случается?

Да

Есть ли случаи, когда вы можете в конечном итоге вызвать метод из AbstractClass (или других классов, если он наследуется несколько раз), даже если это виртуальный метод?

Да, если он не определен в производных классах и не = 0. Если он определен в производных классах, вы все равно можете вызвать версию базового класса с помощью BaseClass :: Method ();

2) кажется, вы не можете создать экземпляр указателя класса, содержащего виртуальные методы. Это правда?

Вы можете создать экземпляр класса, содержащего виртуальные методы, но если они = 0, тогда он является абстрактным, и вы не можете.

1 голос
/ 25 января 2012

1) Да, полиморфизм всегда работает.

2) Вы ошиблись, вы можете создавать экземпляры объектов класса в автоматическом хранилище.

Причина, по которой вы не можете в этом примере, заключается в том, что ваш базовый класс абстрактный.

Это:

AbstractClass * absClass;

объявляет только указатель на базовый класс. Это не создает фактический объект.

Следующее является законным:

ImplementationClass x;

Хотя ImplementationClass является полиморфным типом, вы создаете объект в автоматическом хранилище (в отличие от того, что вы вызываете через указатель). Вы можете сделать это, потому что абстрактные методы из базового класса реализованы в производном классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...