2012-06-27 3 views
5

У меня есть абстрактный базовый класс и вы хотите реализовать функцию в производном классе. Почему мне нужно снова объявить функцию в производном классе?Почему необходимо обновить интерфейс?

class base { 
public: 
    virtual int foo(int) const = 0; 
}; 

class derived : public base { 
public: 
    int foo(int) const; // Why is this required? 
}; 

int derived::foo(int val) const { return 2*val; } 

ответ

7

Учтите, что определение производного класса может быть в заголовке, тогда как его реализация может быть в исходном файле. Заголовок обычно включается во множество мест («единицы перевода»), каждый из которых будет скомпилирован независимо. Если вы не объявили переопределение, компилятор не узнает об этом ни в одной из этих других единиц перевода.

+0

Означает ли это, что если я не переопределяю функцию в производном классе, компилятор не будет искать переопределяющую реализацию производного класса? – Michael

+0

@ Майкл: Да, я думаю, это правильно. –

4

Намерение сделать функцию чистого virtual в базовом классе является то, что производный класс должен переопределить его и обеспечить свою собственную реализацию.
Обратите внимание, что наличие чистой виртуальной функции в классе делает этот класс a Abstract class. Простыми словами класс действует как интерфейс для создания более конкретных классов. Один не может создавать объекты абстрактного класса.

Если вы не переопределите чистую виртуальную функцию в производном классе, тогда производный класс содержит только унаследованную чистую виртуальную функцию класса Base, и сам он также действует как абстрактный класс. Когда ваш производный класс является абстрактным, он не может быть создан.
Итак, чтобы ваш производный класс был создан, он должен переопределить и, следовательно, объявить чистую виртуальную функцию.

+0

Вы правы. Однако, даже если базовый класс не абстрактный, мне нужно обновить функцию, если я хочу перезаписать реализацию. – Michael

1

It is to override the abstraction of the base class.

Если вы не повторно объявляете его, то ваш производный класс также является абстрактным классом. Если вы это сделаете, у вас теперь будет не абстрактный тип базы.

2

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

1

Поскольку иерархия может иметь больше слоев.

struct Base { 
    virtual void foo() const = 0; 
    virtual void bar() const = 0; 
}; 

struct SuperBase: Base { 
    virtual void bar() const override; 
}; 

struct Concrete: SuperBase { 
    virtual void foo() const override; 
}; 

Здесь SuperBase не обеспечивает реализацию для foo, это должно быть указано каким-то образом.

1

В то время как вы не можете создать экземпляр класса с чисто виртуальными функциями, вы можете создать класс вроде этого:

class base { 
public: 
    virtual int foo(int) const = 0; 
}; 

class derived : public base { 
public: 
}; 

class very_derived : public derived { 
public: 
    virtual int foo(int) const { return 2; } 
}; 

Производный класс по-прежнему является абстрактным классом, он не может быть инстанцированный так как оно не переопределяет foo. Вам нужно объявить не чистую виртуальную версию foo, прежде чем вы сможете создать экземпляр класса, даже если вы не определяете foo сразу.

Смежные вопросы