2015-06-30 1 views
-1
class Shape { 
public: 
virtual void draw() = 0; 
. . . 
}; 

class Circle : public Shape { 
public: 
void draw() { . . . } 
. . . 
}; 

class Rectangle : public Shape { 
public: 
void draw() { . . . } 
. . . 
}; 

class Square : public Rectangle { 
public: 
void draw() { . . . } 
. . . 
}; 


Rectangle* rect = new Rectangle; 

rect->draw(); // Statically bound to the draw in the Rectangle class 

В тексте книги, «понятия языка программирования, 10»,Динамический метод связывания

есть часть о динамическом методе связывания.

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

последняя черта над кодом неправильная ??

+0

Я исправил его, есть ошибка –

+0

Достаточно умный оптимизатор может доказать, что 'rect' всегда указывает на экземпляр' Rectangle' в этом примере и привязывается к 'Rectangle :: draw' статически. В любом случае наблюдаемый эффект один и тот же, поэтому непонятно, почему вам будет интересно. –

ответ

0

Концептуально, потому что ничья() представляет собой виртуальный метод, rect->draw() будет всегда консультируйтесь с vtable о Rectangle -derived объекта, на который указывает rect.

Однако

Если компилятор может доказать, что rect на самом деле указывает на экземпляр Rectangle, а не какой-либо другой класс, который является производным от него, который переопределяет метод draw(), то это разрешено (но не требуется), чтобы обойти полиморфный поиск, тем самым сохраняя несколько извлечений памяти.

2

Рассмотрим следующий пример

int main 
{ 
    Shape* cir = new Circle; 
    Shape* rec = new Rectangle; 
    Shape* sqr = new Square; 

    cir->draw(); // Circle::draw 
    rec->draw(); // Rectangle::draw 
    sqr->draw(); // Square::draw 
} 

Все эти переменные cir, rec и sqr являются Shape*, но они будут ссылаться на свои соответствующие draw метод из-за полиморфизма. Это становится еще более ясным, когда мы повторно использовать ту же переменную

int main 
{ 
    Shape* shape = new Circle; 
    shape->draw(); // Circle::draw 
    delete shape; 

    shape = new Rectangle; 
    shape->draw(); // Rectangle::draw 
    delete shape; 

    shape = new Square; 
    shape->draw(); // Square::draw 
    delete shape; 
} 

В этом случае функция draw должна быть решена во время выполнения, так как основной тип shape может быть изменен в течение всего времени выполнения.

0

Нет проблем с вашим кодом, поскольку полиморфные классы virtual вызовы функций разрешены во время выполнения, используя таблицу виртуальных функций, фактически, которая называется динамической привязкой в ​​c++.