2010-06-24 3 views
18

Язык C++ предоставляет функции virtual. В рамках ограничений чистой реализации языка C, как можно добиться аналогичного эффекта?Как реализовать виртуальные функции C++ в C

+2

Почему вы хотите снова реализовать C++? Такие темы можно легко найти в книгах, и есть много онлайн-статей. Задавая такие вопросы, ваша репутация будет затронута, и люди начнут воспринимать вас как должное. Так что сделайте все возможное, чтобы найти ответ, и я все равно не могу спросить :). –

+0

Что вы пытаетесь достичь? – DRL

+0

учитель задал этот вопрос нам – 2010-06-24 20:25:03

ответ

29

Похищенные из here.

Из класса C++

class A { 
protected: 
    int a; 
public: 
    A() {a = 10;} 
    virtual void update() {a++;} 
    int access() {update(); return a;} 
}; 

С-код фрагмент может быть получен. Три функции-члены C++ от class A переписываются с использованием автономного (автономного) кода и собираются по адресу в структуру с именем A_functable. Элементы данных A и объединены с таблицей функций в структуру C с именем A.

struct A; 

typedef struct { 
    void (*A)(struct A*); 
    void (*update)(struct A*); 
    int (*access)(struct A*); 
} A_functable; 

typedef struct A{ 
    int a; 
    A_functable *vmt; 
} A; 

void A_A(A *this); 
void A_update(A* this); 
int A_access(A* this); 

A_functable A_vmt = {A_A, A_update, A_access}; 

void A_A(A *this) {this->vmt = &A_vmt; this->a = 10;} 
void A_update(A* this) {this->a++;} 
int A_access(A* this) {this->vmt->update(this); return this->a;} 

/* 
class B: public A { 
public: 
    void update() {a--;} 
}; 
*/ 

struct B; 

typedef struct { 
    void (*B)(struct B*); 
    void (*update)(struct B*); 
    int (*access)(struct A*); 
} B_functable; 

typedef struct B { 
    A inherited; 
} B; 

void B_B(B *this); 
void B_update(B* this); 

B_functable B_vmt = {B_B, B_update, A_access}; 

void B_B(B *this) {A_A(this); this->inherited.vmt = &B_vmt; } 
void B_update(B* this) {this->inherited.a--;} 
int B_access(B* this) {this->inherited.vmt->update(this); return this->inherited.a;} 

int main() { 
    A x; 
    B y; 
    A_A(&x); 
    B_B(&y); 
    printf("%d\n", x.vmt->access(&x)); 
    printf("%d\n", y.inherited.vmt->access(&y)); 
} 

Более сложный, чем необходимо, но он перекрещивается.

+0

+1 Отличный пример: это примерно так же близко, как вы можете перевести vtables на C и намного шире, чем программисты C, делающие такие вещи, как функции-указатели или кастинговые структуры указателей функций. Он все еще громоздкий и неудобный, но эй, C не был предназначен для этого. – stinky472

+1

@ stinky472: Я согласен с вами, но когда кто-то нуждается в таком коде, это просто не имеет смысла. Некоторые языки лучше подходят для определенных проблем. – Alerty

+0

Очень верно, но я был вынужден работать в системах C, пытающихся реализовать ООП. Они делали это, создавая структуры с указателями функций (например, casting struct A), а не просто передавая A для полиморфизма и позволяя каждой структуре, подобной подклассу, просто хранить A и присваивать ей соответствующие функциональные адреса и данные. Это, по крайней мере, намного более элегантно, чем указатели функций структурирования или литья. – stinky472

-1

Here - описание каких виртуальных функций.

Невозможно реализовать виртуальные функции в plain C, потому что C не имеет понятия наследования.

Update: Как обсуждается в комментариях ниже, можно сделать что-то похожее на виртуальные функции в прямой С помощью структур и указателей на функции. Однако, если вы привыкли к языку C++, который имеет «истинные» виртуальные функции, вы, вероятно, найдете приближение C гораздо менее изящным и более сложным в использовании.

+1

На самом деле, существует понятие наследования в C, но оно не учитывает контроль доступа ACCESS здесь: http://stackoverflow.com/questions/577465/in-c-can-i-derive-a-class-from- a-struct –

+0

@Gollum: структура C++ не похожа на C struct. – Alerty

+2

Вы не можете сделать это напрямую (класс отсутствует :)) - но это не проблема для реализации такой системы с использованием структур и указателей функций. – ManniAT

0

Виртуальные функции - это функция ориентации объектов C++. Они относятся к методам, которые зависят от конкретного экземпляра объекта, а не от того типа, который вы в настоящее время используете для них.

Другими словами: если вы создаете экземпляр объекта как Bar, а затем отбрасываете его в Foo, виртуальные методы по-прежнему будут теми, которые были у экземпляра (определенными в Bar), в то время как другие методы будут такими же, как у Foo.

Виртуальные функции обычно реализуются посредством vtables (это для вас больше исследований;)).

Вы можете имитировать подобные вещи в C, используя структуры как объекты бедного человека и сохраняя в них указатели функций.

(Более правильно, не виртуальные функции делают его неоднозначным, какой класс метод должен быть взят из, но на практике я считаю, C++ использует текущий тип.)

1

@GCC .... Виртуальная функция объявляется в базовом классе объекта и затем «переопределяется» или реализуется в подклассах. например, у вас есть класс Vehicle Base, и вы создаете два подкласса, мотоцикл и автомобильный. Базовый класс объявит виртуальную функцию AddTires(). Затем Sub Classes будут реализовывать эту функцию, и каждый подкласс будет реализовывать ее по-разному. Автомобиль имеет 4 колеса, где мотоцикл имеет 2. Я не могу дать вам синтаксис для C или C++. Надеюсь, это поможет

+0

Конечно, мой ответ основан на C# и этой объектной модели – MikeTWebb