2017-02-17 15 views
3
class base 
{ 
public: 
std::string name() { return basename; } 
virtual void print(std::ostream &os) { os << basename; } 
private: 
std::string basename = "base\n"; 
}; 

class derived : public base 
{ 
public: 
void print(std::ostream &os) override { base::print(os); os << " derived\n " << i; } 

private: 
int i; 
}; 

int main() 
{ 
// ex15.14 
base bobj; 
base *bp1 = &bobj; 
base &br1 = bobj; 
derived dobj; 
base *bp2 = &dobj; 
base &br2 = dobj; 

// a. this is an object, so compile time. 
//bobj.print(std::cout); 

// b. this is an object, so compile time. 
//dobj.print(std::cout); 

// c. function name is not virtual , so no dynamic 
//  binding happens.so compile time 
//std::cout << bp1->name(); 

// d. function name is not virtual , so no dynamic 
//  binding happens.so compile time 
//std::cout << bp2->name(); 

// e. run time 
//br1.print(std::cout); 

// f. run time 
//br2.print(std::cout); 


return 0; 
} 

注意事項eおよびf、br1およびbr2は、基本クラスオブジェクトbobjおよび派生クラスオブジェクトdobjへの参照です。良いC++コンパイラがコードを検出して最適化できるので、動的バインディング処理はまったくできません。コンパイラは動的バインディングをどの程度静的に変更しますか?

+0

はい、[時々](https://godbolt.org/g/8ksE9t)はそうです。 :-) – WhiZTiM

+0

はい、確かです。コンパイラはコンパイル時に動的型を知ることができ、派生クラスのメンバへの呼び出しを発行します。ただし、コードでは基本クラス型への参照が使用されます。 – IInspectable

答えて

5

はい。コンパイラが仮想メソッド呼び出しが常に同じタイプのオブジェクトを対象とすることがあることを静的に証明できれば、ディスパッチベクトルを使用せずに実際の実装に静的にバインドするように呼び出しを最適化することができます。

この分析は、通常、コンパイラーによって効率的に実行できる単純な状況依存型、フロー非依存型のポインター分析の変種です。当然、すべての可能な最適化ポイントを検出するわけではありませんが、明白な点に当てはまる可能性はあります。

これは、Javaのように常に動的ディスパッチを使用する言語を効率的にコンパイルするための重要な手法です。

関連する問題