Интересная абстрактная функция C ++

почему это случилось?

Когда вы создаете абстрактный класс в C ++, Ex: Class A (который имеет чисто виртуальную функцию) после этого класса B наследуется от класса A

А если класс А имеет конструктор с именем A () Предположим , я создал объект из класса B , то компилятор инициализирует базовый класс первый т.е. класс А , а затем инициализирует класс B Тогда .......?

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

13.12.2008 09:43:17
5 ОТВЕТОВ
РЕШЕНИЕ

Быстрый ответ: конструкторы особенные.

Когда конструктор A все еще работает, тогда конструируемый объект еще не относится к типу A. Он все еще создается. Когда конструктор заканчивается, это теперь А.

То же самое для производного B. Конструктор для A запускается первым. Теперь это A. Затем конструктор для B начинает работать. Во время этого объект все еще на самом деле является A. Только после завершения конструктора B он становится B.

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

Компилятор не позволит вам сгенерировать код, который будет создавать A из-за чисто виртуальной функции. Но он сгенерирует код для построения A как часть процесса построения B. В этом нет никакой магии. Правило, что вы не можете построить А, навязывается правилами языка, а не физикой. Язык отменяет это правило в особых условиях конструирования объектов Б.

8
13.12.2008 10:56:54
После попытки вызвать виртуальный метод из конструктора и увидеть результат, всегда помните, чтобы не вызывать виртуальные методы в конструкторах :)
David Rodríguez - dribeas 13.12.2008 12:42:52
И затем забудьте это правило в C ++ / CLI, где оно не применяется!
Daniel Earwicker 13.12.2008 17:44:06

class Aабстрактно, но class Bнет. Чтобы построить class B, он должен реализовать все чисто виртуальные функции-члены class A.

class A
{
public:
    A() {}
    virtual ~A() {}
    virtual void foo() = 0; // pure virtual
    int i;
};


class B : public A
{
public:
    B() {}
    virtual ~B() {}
    virtual void foo() {}
    int j;
};

Макет класса A может выглядеть примерно так:

+ --------- + + --------- +
| VFtable | -> | ~ A () | -> адрес A :: ~ A ()
+ --------- + + --------- +
| я | | foo () | -> NULL, чистый виртуальный
+ --------- + + --------- +

Макет класса B может выглядеть примерно так:

+ --------- + + --------- +
| VFtable | -> | ~ B () | -> адрес B :: ~ B ()
+ --------- + + --------- +
| я | | foo () | -> адрес B :: foo ()
+ --------- + + --------- +
| J |
+ --------- +
4
13.12.2008 10:42:37
Спасибо за ответ, но я хочу знать, как он создает внутренний объект абстрактного класса ??????
Access Denied 13.12.2008 09:59:57
Смешно закончился сложным ответом на простой вопрос.
Martin York 13.12.2008 17:11:35
Возможно, я сначала сделал простой ответ, но он не ответил на вопрос Даршана.
dalle 14.12.2008 08:58:42
struct A {
  A(int x) {..}
  virtual void do() = 0;
};

struct B : public A {
   B() : A(13) {}      // <--- there you see how we give params to A c'tor
   virtual void do() {..}
};
1
13.12.2008 10:17:04
 And if class A has constructor called A() suppose i created an
 Object of class B then the compiler initializes the base class
 first i.e.class A and then initialize the class B
 Then.......?

На самом деле вы ошибаетесь:

Когда вы создаете объект класса B, вызывается конструктор B.
Если вы не укажете, как конструктор B вызывает конструктор A, тогда компилятор автоматически вставит в качестве первого действия в списке инициализатора вызов конструктора по умолчанию A.

Если вы не хотите использовать конструктор по умолчанию, вы должны явно поместить вызов соответствующего конструктора A в качестве первого элемента в списке инициализатора.

Когда строительство A будет завершено, строительство B будет продолжено.

First thing is we can not access a constructor of any class without an Object
then how it is initialize the constructor of abstract class if we can not create
an object of abstract class .

Вы произносите вышесказанное так, как будто вы рассматриваете А и Б по-разному. Объект класса B также является объектом класса A. Это действительный объект в целом. Весь объект принадлежит классу B, но он содержит (как часть того же объекта) всю информацию, которая была из класса A.

0
13.12.2008 17:26:34

Тот факт, что вы не можете создать экземпляр класса Aнапрямую, не означает, что создать экземпляр класса невозможно A. Вам не разрешено создавать экземпляры, Aпотому что компилятор знает, что Aэто абстрактно, и отклоняет любой код, который вы пишете, который пытается напрямую создать экземпляр A. Это запрещает код, подобный этому:

A a;
new A();

Что делает класс абстрактным, так это то, что он имеет чисто виртуальные методы. Тем не менее, ничто не мешает созданию такого класса. Стандарт C ++ просто говорит, что это запрещено. Компилятор вполне способен генерировать инструкции для создания экземпляра абстрактного класса. Все, что ему нужно сделать, - зарезервировать нужное количество памяти и затем вызвать конструктор, так же, как это было бы для неабстрактного класса.

Когда вы создаете экземпляр B, вся память для класса выделяется сразу. Поскольку все байты есть, там, по сути, есть Aэкземпляр, готовый для инициализации конструктором. (Но обратите внимание , что память не формально не считается объектом типа Aдо тех пор , послеA того, как конструктор закончит работу.) В Aконструкторе работает, а затем Bработает конструктор.

0
13.12.2008 17:46:29