Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > реализация виртуального метода в наследнике


Автор: boostcoder 19.7.2012, 21:19
халоф пиплы!

сегодня был озадачен следующим.
имеем базовый абстрактный класс описанный в хидере base.hpp:
Код

struct base {
    virtual void m() = 0;
};


далее, наследуем его в класс derived, описанный в derived.hpp:
Код

#include "base.hpp"

struct derived: base {
    void m2();
};


и далее, пытаемся реализовать base::m() в наследнике в его .cpp файле:
Код

#include "derived.hpp"

void derived::m2() {}

void derived::m() {}

int main() {
    derived d;
}

то получаю:
Цитата

derived.cpp:6:17: error: no 'void derived::m()' member function declared in class 'derived'
derived.cpp: In function 'int main()':
derived.cpp:9:10: error: cannot declare variable 'd' to be of abstract type 'derived'
derived.hpp:4:8: note:   because the following virtual functions are pure within 'derived':
base.hpp:3:15: note:  virtual void base::m()


я чего-то недопонимаю? или что?

спасибо.



зы
если его реализовать прям внутри декларации derived - то все ок.

Автор: Qu1nt 19.7.2012, 21:36
Ты забыл объявить метод m в derived.

Автор: boostcoder 19.7.2012, 21:42
Qu1nt, т.е. я должен продублировать декларации методов предка в наследнике?
а как же http://en.wikipedia.org/wiki/One_Definition_Rule?  smile 

Автор: Randajad 19.7.2012, 21:54
А оно к этому случаю относится? О.о

Автор: borisbn 19.7.2012, 22:07
Цитата(boostcoder @  19.7.2012,  21:42 Найти цитируемый пост)
т.е. я должен продублировать декларации методов предка в наследнике?

 smile 
ващето не "должен", а "обязан"

Автор: boostcoder 19.7.2012, 22:08
а двойная декларация одного и того же, разве не относится к ODR? oO

Автор: mes 19.7.2012, 22:15
boostcoder, может в отпуск пора ? smile

Добавлено через 2 минуты и 2 секунды
Цитата(boostcoder @  19.7.2012,  21:08 Найти цитируемый пост)
 декларация одного и того же, разве не относится к ODR?

декларация (обьявление) может быть сколь угодно много раз.. это вот с определениями проблема..

Добавлено через 3 минуты и 36 секунд
ODR - one definition rule, not one declaration rule..

Автор: boostcoder 19.7.2012, 22:19
mes, пора. надеюсь со следующей недели выйду.
но все равно не понимаю, зачем мне дважды декларировать одни и те же методы smile 
допустим, в предке я изменю декларацию метода. так мне что, нужно во всех наследниках проделать то же самое? где логика?

Автор: mes 19.7.2012, 22:21
Цитата(boostcoder @  19.7.2012,  21:19 Найти цитируемый пост)
но все равно не понимаю, зачем мне дважды декларировать одни и те же методы

c++ потому что.. 

Автор: boostcoder 19.7.2012, 22:21
Цитата(mes @  19.7.2012,  22:15 Найти цитируемый пост)
ODR - one definition rule, not one declaration rule.

это я-то понимаю. но вод по логике, что-то тут не вяжется...

Добавлено через 1 минуту и 8 секунд
Цитата(mes @  19.7.2012,  22:21 Найти цитируемый пост)
c++ потому что.

аааа, ну да. так можно на любой вопрос по С++ ответить =)

в общем понял, что так оно и задумывалось.
всем спасибо.

Автор: mes 19.7.2012, 22:24
Цитата(boostcoder @  19.7.2012,  21:21 Найти цитируемый пост)
это я-то понимаю. но вод по логике, что-то тут не вяжется... 

ага - лишний труд )

Добавлено через 3 минуты и 13 секунд
Цитата(boostcoder @  19.7.2012,  21:21 Найти цитируемый пост)
аааа, ну да. так можно на любой вопрос по С++ ответить =)

но на этот по другому никак не ответить smile

Автор: boostcoder 19.7.2012, 22:32
Цитата(mes @  19.7.2012,  22:24 Найти цитируемый пост)
на этот по другому никак не ответить

 smile 
пора на D переходить. скоро в GCC добавят поддержку.

Автор: bsa 19.7.2012, 23:49
Цитата(boostcoder @  19.7.2012,  23:32 Найти цитируемый пост)
пора на D переходить. скоро в GCC добавят поддержку.

Угу. Только осталось дождаться библиотек под него...

Автор: xvr 20.7.2012, 11:33
Цитата(boostcoder @  19.7.2012,  22:19 Найти цитируемый пост)
но все равно не понимаю, зачем мне дважды декларировать одни и те же методы

Они не одни и те же. Декларация derived::m говорит компилятору, что вы собираетесь перебить виртуальный метод m в наследнике. Без этой декларации и без самого модуля с реализацией компилятор не сможет правильно сформировать таблицу виртуальных методов класса derived в других модулях, где он используется

Автор: boostcoder 20.7.2012, 12:27
Цитата(xvr @  20.7.2012,  11:33 Найти цитируемый пост)
Декларация derived::m говорит компилятору, что вы собираетесь перебить виртуальный метод m в наследнике.

он чисто виртуальный. перебить его не получится до тех пор, пока он не реализован. на основании этого, компилятор точно знает что в наследнике происходит не переопределение, а реализация.

мне так думается...

Автор: xvr 20.7.2012, 16:50
Цитата(boostcoder @  20.7.2012,  12:27 Найти цитируемый пост)
на основании этого, компилятор точно знает что в наследнике происходит не переопределение, а реализация.

Компилятор не знает, а происходит ли она вообще (если он не видит описания класса).

Автор: boostcoder 20.7.2012, 18:13
Цитата(xvr @  20.7.2012,  16:50 Найти цитируемый пост)
Компилятор не знает

как это незнает?
при компиляции cpp`ишки, компилятор получает декларацию. из нее он все знает.
или что?

Автор: xvr 20.7.2012, 20:18
Цитата(boostcoder @  20.7.2012,  18:13 Найти цитируемый пост)
при компиляции cpp`ишки, компилятор получает декларацию. из нее он все знает.

Не все он знает ...
Вот ваша декларация -
Код

#include "base.hpp"
struct derived: base {
    void m2();
};
Допустим это находится в include и включается в другой cpp файл (не тот, где методы derived описаны)
Теперь я в нем делаю 
Код

base* p=new derived;
Что должен сделать компилятор? Судя по декларации derived - чисто виртуальный класс, и компилятор не в курсе, что вы ему derived::m() в другом файле описали.
Более того, даже если base::m будет не чисто виртуальной, как компилятор здесь (положим, что он захочет именно здесь это сделать) будет формировать таблицу виртуальных методов для derived? Что он должен положить в  vtbl::m ? Откуда он узнает, что вы ее где то описали в другом месте?

Автор: boostcoder 21.7.2012, 07:52
xvr, да, Вы правы.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)