2013-05-07 6 views
0
#ifndef TEST_H 
#define TEST_H 
#include <iostream> 
#include <string> 
class A{ 
public: 
    virtual void test1() = 0; 
    virtual std::string test2() = 0; 
}; 

class B : public A{ 

public: 
    void test1(){ 
     std::cout << A::test2() << " World"; 
    } 
}; 
class C : public B{ 
public: 
    std::string test2(){ 
     return "hello"; 
    } 
}; 
class C1 : public B{ 
public: 
    std::string test2(){ 
     return "Sup"; 
    } 
}; 

#endif // TEST_H 

У меня есть интерфейс A с чистыми виртуальными методами. У меня есть абстрактный класс, который хочет реализовать test1 и использовать test2 для реализации test1.Использовать чистые виртуальные методы в абстрактном классе

Теперь C и C1 и мои конкретные классы, которые реализуют test2

Но я не могу сделать std::cout << A::test2() << " World"; в классе B

error: cannot call member function 'virtual std::string A::test2()' without object

Как бы сделать что-то подобное в C++?

+1

'A' и' B' вообще не связаны.Поэтому вы не можете этого сделать. Чтобы иметь возможность сделать это, «B» нужно наследовать от «A», я не уверен, насколько это соответствует вашему дизайну. –

+0

Для класса, реализующего интерфейс 'A', он должен фактически _inherit_ от' A'. –

+0

Да, это была опечатка, я сожалею. –

ответ

3

Не зацикливайтесь на виртуальном виртуальном виртуальном. Обе функции, объявленные в A, являются виртуальными, и вы можете просто рассматривать их как таковые. Таким образом, реализация Btest1 должна просто называть test2. Нет A:: квалификатор. Это делает виртуальный вызов и заканчивается в самой производной версии test2, то есть той, которая определена в C или C1, в зависимости от типа объекта. После того, как я удалил A:: из A::test2(), следующий код работает (как это должно быть):

int main() { 
    C c; 
    c.test1(); 
    C1 c1; 
    c1.test1(); 
    return 0; 
} 

[work]$ g++ test.cpp 
[work]$ ./a.out 
hello WorldSup World[work]$ 

Да, вы должны добавить \n к выходу. <g>

2

Ваш class B необходимо наследовать от class A.

class B: public A ... 

Конечно, вызов A::test2() не будет работать, так как этот класс не будет реализован - он не имеет тела. Вы могли бы решить, что также путем его реализации в классе А, как это:

std::string A::test2() { return "some string"; } 
+0

Предполагается, что это встроенная чистая виртуальная функция? Стандартные чистые виртуальные функции не допускаются стандартом. Вы должны определить его вне тела класса. –

+0

Действительно? Я никогда не использовал «реализованные чистые виртуальные», но я думал, что вы можете их встроить. Но я его отредактирую. –

+0

Я так запутался прямо сейчас. Не могли бы вы уточнить, что мне делать? –

2

Не используйте явную квалификацию области действия, если вы хотите виртуальный вызов. С помощью A::test2 попытается позвонить A::test2, без динамической отправки. И это, в свою очередь, не будет связываться, потому что A::test2 не имеет реализации.

+0

Итак, вы говорите, что я просто вызываю test2(); вместо A :: test2(); ? Я получаю тот же результат. –

+0

Когда я пытаюсь это сделать, я получаю совершенно разные результаты от вас. В частности, ваш исходный код компилируется, но не связывается (компоновщик жалуется, что не может найти реализацию A :: test2). Если я удалю A ::, он скомпилируется и работает правильно. Таким образом, либо вы используете очень глючный компилятор, либо не публиковали код, который используете. Вы где-то заблудились? –

+0

Хорошо, ничего себе. Я использовал GCC 4.8, который вызывает некоторые ошибки. Но он прекрасно компилируется в clang. –

2

сообщение об ошибке означает, что, когда он был скомпилирован, B не унаследовали от A, так что не было ни одного объекта типа A вызвать функцию-член. Код, который вы опубликовали, дает мне другую ошибку: A::test2 не определен.

Почти наверняка вы хотите фактически вызвать функцию (то есть вызвать окончательное переопределение в C или C1 или что-то еще). В этом случае не имеют права это вообще:

std::cout << test2() << std::endl; 

Ваш код пытается конкретно назвать версию объявлен в A, а не какой-либо переопределения. Если это на самом деле то, что вы хотите (в чем я сомневаюсь), то эта функция должна быть определена:

std::string A::test2() { 
    return "I'm a pure virtual function. Why are you calling me?"; 
} 

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

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