2013-11-29 7 views
-3

Мой вопрос заключается в следующем:Реализация виртуальных функций без виртуального ключевого слова

Я хочу (если это возможно), чтобы «осуществлять» виртуальные функции, не используя «виртуальный» ключевое слово (из любопытства - я знаю трюк с указателями функций в C, я хочу сделать это в C++ !!). Моей «идеей» является наличие флага, который будет назначен в конструкторе, чтобы указать, к какому экземпляру этот объект. Мои вопросы: 1) Возможно ли это? 2) Если так - что я делаю неправильно? или чего не хватает?

Я использую г ++, который дает мне эти ошибки:

#‘B’ has not been declared 

#‘C’ has not been declared 

#class ‘B’ does not have any field named ‘flag’ 

#class ‘C’ does not have any field named ‘flag’ 

Это мое предложение:

#include <iostream> 
using namespace std; 

class A { 

protected: 
    short flag; 
public: 
    A(int f = 1) : flag(f) {} 
    void foo() 
    { 
     switch (this->flag) 
    { 
     case 1: cout << "A " << endl; break; 

     case 2: B :: foo(); break; 

     case 3: C :: foo(); break; 
    } 
    } 
}; 

class B : public A{ 

public: 
B(int f = 2) : A(f) {} 
void foo() {cout << "B " << endl;} 
}; 


class C : public B{ 

public: 
    C(int f = 3) : B(f) {} 
    void foo() {cout << "C " << endl;} 
}; 

int main() 
{ 
    A a; 
    B b; 
    C c; 

    A *pb = &b; 
    A *pc = &c; 

    a.foo(); 
    pb->foo(); 
    pc->foo(); 

    return 0; 
} // end main 

Спасибо отчислять (!!) заранее, Гай.

+3

Только один вопрос: почему? Это проблема XY? –

+1

C++ имеет виртуальное ключевое слово точно так, что вам не нужно это делать. –

+0

Разумеется, c-front используется для реализации всех объектов C++ Object, включая динамическую диспетчеризацию для виртуальных машин с C-кодом. Конечно, это нецелесообразно, vtables - это боль для создания и управления, а действия операторов - мерзость. – RichardPlunkett

ответ

1

Возможно ли это?

Да. Возможно, это нецелесообразно, поскольку оно более подвержено ошибкам, чем виртуальные функции, и требует, чтобы базовый класс знал обо всех производных классах, но это, безусловно, возможно, и вы почти там.

Если так - что я делаю неправильно?

Вам нужно переместить определение A::foo из класса, после определения B и C, так что он может использовать эти классы.

Вам потребуется явное потупив доступ к функциям членов производных классов:

static_cast<B*>(this)->foo(); 
+0

, но его не статичный литой, его динамический бросок наверняка? – RichardPlunkett

+0

@RichardPlunkett: Чтобы быть уверенным, что актер действителен, вы можете использовать 'dynamic_cast'. Но это было бы намного медленнее и было бы необходимо, только если вы не доверяете 'flag', чтобы иметь правильное значение. –

+0

@RichardPlunkett: На самом деле 'dynamic_cast' не будет работать, поскольку эти классы не являются полиморфными. –

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