Язык C++ предоставляет функции virtual
. В рамках ограничений чистой реализации языка C, как можно добиться аналогичного эффекта?Как реализовать виртуальные функции C++ в C
ответ
Похищенные из 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));
}
Более сложный, чем необходимо, но он перекрещивается.
+1 Отличный пример: это примерно так же близко, как вы можете перевести vtables на C и намного шире, чем программисты C, делающие такие вещи, как функции-указатели или кастинговые структуры указателей функций. Он все еще громоздкий и неудобный, но эй, C не был предназначен для этого. – stinky472
@ stinky472: Я согласен с вами, но когда кто-то нуждается в таком коде, это просто не имеет смысла. Некоторые языки лучше подходят для определенных проблем. – Alerty
Очень верно, но я был вынужден работать в системах C, пытающихся реализовать ООП. Они делали это, создавая структуры с указателями функций (например, casting struct A), а не просто передавая A для полиморфизма и позволяя каждой структуре, подобной подклассу, просто хранить A и присваивать ей соответствующие функциональные адреса и данные. Это, по крайней мере, намного более элегантно, чем указатели функций структурирования или литья. – stinky472
Here - описание каких виртуальных функций.
Невозможно реализовать виртуальные функции в plain C, потому что C не имеет понятия наследования.
Update: Как обсуждается в комментариях ниже, можно сделать что-то похожее на виртуальные функции в прямой С помощью структур и указателей на функции. Однако, если вы привыкли к языку C++, который имеет «истинные» виртуальные функции, вы, вероятно, найдете приближение C гораздо менее изящным и более сложным в использовании.
На самом деле, существует понятие наследования в C, но оно не учитывает контроль доступа ACCESS здесь: http://stackoverflow.com/questions/577465/in-c-can-i-derive-a-class-from- a-struct –
@Gollum: структура C++ не похожа на C struct. – Alerty
Вы не можете сделать это напрямую (класс отсутствует :)) - но это не проблема для реализации такой системы с использованием структур и указателей функций. – ManniAT
Виртуальные функции - это функция ориентации объектов C++. Они относятся к методам, которые зависят от конкретного экземпляра объекта, а не от того типа, который вы в настоящее время используете для них.
Другими словами: если вы создаете экземпляр объекта как Bar, а затем отбрасываете его в Foo, виртуальные методы по-прежнему будут теми, которые были у экземпляра (определенными в Bar), в то время как другие методы будут такими же, как у Foo.
Виртуальные функции обычно реализуются посредством vtables (это для вас больше исследований;)).
Вы можете имитировать подобные вещи в C, используя структуры как объекты бедного человека и сохраняя в них указатели функций.
(Более правильно, не виртуальные функции делают его неоднозначным, какой класс метод должен быть взят из, но на практике я считаю, C++ использует текущий тип.)
@GCC .... Виртуальная функция объявляется в базовом классе объекта и затем «переопределяется» или реализуется в подклассах. например, у вас есть класс Vehicle Base, и вы создаете два подкласса, мотоцикл и автомобильный. Базовый класс объявит виртуальную функцию AddTires(). Затем Sub Classes будут реализовывать эту функцию, и каждый подкласс будет реализовывать ее по-разному. Автомобиль имеет 4 колеса, где мотоцикл имеет 2. Я не могу дать вам синтаксис для C или C++. Надеюсь, это поможет
Конечно, мой ответ основан на C# и этой объектной модели – MikeTWebb
Почему вы хотите снова реализовать C++? Такие темы можно легко найти в книгах, и есть много онлайн-статей. Задавая такие вопросы, ваша репутация будет затронута, и люди начнут воспринимать вас как должное. Так что сделайте все возможное, чтобы найти ответ, и я все равно не могу спросить :). –
Что вы пытаетесь достичь? – DRL
учитель задал этот вопрос нам – 2010-06-24 20:25:03