本文介绍了 C++ 的 5 个特别用法(Idioms),分别是
addressof()
;Attorney-Client; Calling Virtuals During Initialization; Capability Query; Clear-and-minimize;
01. addressof()
用途
类可以重载 &
使其违反“取对象地址”的本意,此时可以通过 addressof()
获得对象地址
示例代码
#include <iostream>
using namespace std;
class UnAddressable
{
private :
double operator & ( ) const { return 0.0 ; }
} ;
int main ( ) {
UnAddressable na;
UnAddressable* naptr1 = & na;
UnAddressable* naptr2 = addressof ( na) ;
cout << "Address of an UnAddressable object: " << naptr2 << endl;
return 0 ;
}
02. Attorney-Client
用途
提供类内实现细节的有选择性(部分)可访问 C++ 中类的友元 friend
可以全权访问类内的实现细节,这就破坏了封装性,但 friend
主张 “all or nothing”,无法实现对私有成员的有选择访问 Attorney-Client 方法
示例代码
没有继承的情况
class Client
{
friend class Attorney ;
private :
void func1 ( ) { }
void func2 ( ) { }
void func3 ( ) { }
} ;
class Attorney
{
friend class Bar ;
private :
static void call_func1 ( Client& c) { c. func1 ( ) ; }
static void call_func2 ( Client& c) { c. func2 ( ) ; }
} ;
class Bar
{
} ;
存在继承时
#include <iostream>
using namespace std;
class Base
{
friend class Attorney ;
public :
virtual ~ Base ( ) { }
private :
virtual void func ( ) { cout << "Base::func()" << endl; }
} ;
class Derived : public Base
{
public :
~ Derived ( ) { }
private :
virtual void func ( ) { cout << "Derived::func()" << endl; }
} ;
class Attorney
{
friend int main ( ) ;
private :
static void call_func ( Base* base) {
return base- > func ( ) ;
}
} ;
int main ( ) {
Base* d1 = new Base;
Attorney:: call_func ( d1) ;
Base* d2 = new Derived;
Attorney:: call_func ( d2) ;
return 0 ;
}
03. Calling Virtuals During Initialization
用途
在派生类对象初始化期间调用虚函数,也称为初始化期间的动态绑定
示例代码
class Base
{
public :
Base ( ) { func1 ( ) ; func2 ( ) ; }
virtual ~ Base ( ) { }
virtual void func1 ( ) const { }
virtual void func2 ( ) const { }
} ;
class Derived : public Base
{
public :
virtual void func1 ( ) const { }
virtual void func2 ( ) const { }
} ;
class Base
{
public :
virtual ~ Base ( ) { }
void init ( ) { func1 ( ) ; func2 ( ) ; }
virtual void func1 ( ) const { cout << "Base::func1()" << endl; }
virtual void func2 ( ) const { cout << "Base::func2()" << endl; }
} ;
class Derived : public Base
{
public :
Derived ( const char * s) { cout << s << endl; }
virtual void func1 ( ) const { cout << "Derived::func1()" << endl; }
virtual void func2 ( ) const { cout << "Derived::func2()" << endl; }
} ;
shared_ptr< Base> factory ( )
{
shared_ptr< Base> ptr ( new Derived ( "Derived class" ) ) ;
ptr- > init ( ) ;
return ptr;
}
int main ( ) {
shared_ptr< Base> b1 = factory ( ) ;
return 0 ;
}
04. Capability Query
用途
在运行时检查对象是否支持某个接口 当一个类继承自多个基类时,可能无法预知它实现了哪个特定接口 通过 dynamic_cast
进行“试探”
示例代码
class Shape
{
public :
virtual ~ Shape ( ) { }
virtual void draw ( ) const = 0 ;
} ;
class Rollable
{
public :
virtual ~ Rollable ( ) { }
virtual void roll ( ) = 0 ;
} ;
class Circle : public Shape, public Rollable
{
public :
void draw ( ) const { cout << "Drawing a circle." << endl; }
void roll ( ) { cout << "Circle is rolling." << endl; }
} ;
class Square : public Shape
{
public :
void draw ( ) const { cout << "Drawing a sqaure." << endl; }
} ;
int main ( ) {
Shape* shape1 = new Circle;
Shape* shape2 = new Square;
if ( Rollable* rollable = dynamic_cast < Rollable* > ( shape1) )
rollable- > roll ( ) ;
if ( Rollable* rollable = dynamic_cast < Rollable* > ( shape2) )
rollable- > roll ( ) ;
return 0 ;
}
05. Clear-and-minimize
用途
也叫 swap with temporary 清空一个容器,并将其容量最小化
示例代码
int main ( ) {
vector< int > int_vec{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 } ;
int_vec. push_back ( 100 ) ;
int_vec. push_back ( 101 ) ;
int_vec. push_back ( 102 ) ;
int_vec. push_back ( 103 ) ;
cout << "Capacity of int_vec: " << int_vec. capacity ( ) << endl;
int_vec. erase ( int_vec. begin ( ) + 5 , int_vec. end ( ) ) ;
cout << "Capacity of int_vec: " << int_vec. capacity ( ) << endl;
vector< int > ( ) . swap ( int_vec) ;
cout << "Capacity of int_vec: " << int_vec. capacity ( ) << endl;
return 0 ;
}