2008-12-13 4 views
3

Почему это происходит?Интересная C++ Абстрактная функция

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

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

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

ответ

8

Быстрый ответ: Конструкторы являются специальными.

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

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

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

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

4

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; 
}; 

Аналого макет класс может быть что-то вроде этого:

 
+---------+  +---------+ 
| vftable | --> | ~A() | --> address of A::~A() 
+---------+  +---------+ 
| i  |  | foo() | --> NULL, pure virtual 
+---------+  +---------+ 

Б макет класс может быть что-то вроде этого:

 
+---------+  +---------+ 
| vftable | --> | ~B() | --> address of B::~B() 
+---------+  +---------+ 
| i  |  | foo() | --> address of B::foo() 
+---------+  +---------+ 
| j  | 
+---------+ 
+0

Спасибо за ответ, но я хочу знать, что он создает внутренний объект абстрактного класса ?????? – 2008-12-13 09:59:57

+0

Смешно над сложным ответом на простой вопрос. – 2008-12-13 17:11:35

1
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() {..} 
}; 
0
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 завершена, конструкция 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 . 

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

0

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

A a; 
new A(); 

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

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

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