Использовать абстракцию внутри базы, ожидая, что это будет производный класс?

возьмите этот простой код:

class A{ 
  public: 
  virtual void foo() = 0; 
  void x(){ foo(); }
};
class B: public A{ foo(){ ... } };

main(){
  B b;
  b.x();
}

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

Вопрос в том, что я не могу заставить эту работу работать, компилятор говорит, что не может скомпилировать, потому что не может найти ссылку (или что-то в этом роде) на foo() для выполнения в x() из базовый класс. Может ли это работать? Может ли кто-нибудь привести мне пример этого?

РЕДАКТИРОВАТЬ: кажется, что это просто не работает, когда "foo();" находится внутри деструктора класса A (базового)...
Это меня просто смутило. знак равно

EDIT2: как это интересно. Я только что создал callfoo(){ foo(); } и теперь он компилируется нормально, но если я попытаюсь вызвать чистую абстрактную функцию непосредственно из деструктора базового класса A, это выдаст мне ошибки... странно. Кто-нибудь знает об этом? О_о

любая помощь в этом, пожалуйста?

Спасибо,
Джонатан

Обновить

Он работал вне деструктора. Сейчас я просто запутался.

Попробуйте поместить "foo()" внутри деструктора класса A(base), по крайней мере, для меня это не компилируется...

любая помощь плз?


person Jonathan    schedule 05.04.2010    source источник
comment
Я вернусь сюда, чтобы принять любой ответ по этому поводу, если я делаю что-то не так или нет, я использую gcc 4.3.2 в Linux-боксе внутри vmware... Спасибо за все ответы, мне очень нравится этот сайт. много...   -  person Jonathan    schedule 05.04.2010
comment
Все дело в эффективности. Наиболее эффективный способ создания и уничтожения объектов может быть достигнут только в том случае, если при конструировании части A объекта B вы ничего не знаете о самом B (и поэтому не можете вызывать его методы).   -  person baol    schedule 05.04.2010


Ответы (4)


Вам ничего не мешает это сделать:

struct A {
    virtual ~A() {}
    virtual void f() = 0;
    virtual void g() { f(); }
};

struct B : A {
    void f() { std::cout << "B::f()" << std::endl; }
};

// ...
A* a = new B;
a->g(); // prints "B::f()"

Что касается вызова чистой виртуальной функции из деструктора (или конструктора): Не делайте этого! Это вызывает неопределенное поведение.

§10.4/6:

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

person Georg Fritzsche    schedule 05.04.2010
comment
Мне нравится касание виртуального деструктора :) - person baol; 05.04.2010
comment
Я пытаюсь создать класс, который должен иметь DeleteItens как абстрактную функцию, которая будет вызываться внутри деструктора базового класса. Но я все еще получаю неопределенную ссылку = [ - person Jonathan; 05.04.2010
comment
@Jonathan: Можете ли вы обновить вопрос примером, демонстрирующим проблему, или задать вопрос конкретно о проблеме, с которой вы столкнулись? - person Georg Fritzsche; 05.04.2010
comment
Я обновил вопрос, это поможет вам понять меня? Мне не хватает английского =[ - person Jonathan; 05.04.2010
comment
какая странная вещь не правда ли. Я просто добавил его в другую функцию, и он, по крайней мере, скомпилировался, теперь я собираюсь проверить... Но все равно странно. Спасибо за ответ - person Jonathan; 05.04.2010
comment
Смотрите обновление, которое я добавил, это должно прояснить это. Основная проблема в том, что вы ожидаете от базового конструктора? Вызов производного класса бесполезен, его деструктор вызывается перед деструктором базового класса. - person Georg Fritzsche; 05.04.2010
comment
да, компилируется, но не запускается... Думаю, придется искать другой способ. Иногда я нахожу C++ таким странным. Мне это нравится больше всего, но есть кое-что, что не имеет для меня особого смысла... Конечно, мои знания очень мало близки к тому, кто создал логику этого, но как программист я стараюсь всегда понимать логику за вещами - person Jonathan; 05.04.2010
comment
Если вы хотите лучше понять это, например. Облегченная версия часто задаваемых вопросов по С++ имеет некоторую обработку виртуальных функций: parashift.com/c++- faq-lite/virtual-functions.html - person Georg Fritzsche; 05.04.2010

Он должен работать с несколькими синтаксическими модификациями.

#include <iostream>

class A { 
  public: 
  virtual ~A() {}
  virtual void foo() = 0; 
  void x() { foo(); }
};

class B: public A{ 
    void foo(){ std::cerr << "bingo!" << std::endl; } 
};

int main(){
  B b;
  b.x();
  return 0;
}

$ g++ -Wall -Weffc++ derived.cc 
$ ./a.out 
bingo!

Эта технология совершенно легальна.

person baol    schedule 05.04.2010

Похоже, что вы ищете реализацию шаблона метода шаблона.

Вам нужно использовать указатели, чтобы воспользоваться полиморфизмом (таким образом, избегая сообщения... x не является членом B)

#include <iostream>                                                             

class A{  
  public: 
    virtual void foo() = 0;  
    virtual void x(){ foo(); }
};  
class B: public A{  
        void foo(){ std::cout<<"this is b"<<std::endl; } 
};

int main(){
 A* b= new B();
 b->x();

 return 0;
 }   
person Tom    schedule 05.04.2010
comment
x() является членом B. Он публично наследуется от A. - person Ben Voigt; 05.04.2010

Теоретически это работает так же хорошо, но вы должны добавить возвращаемый тип в foo() класса B.

person Ricardo Ferreira    schedule 05.04.2010