C++で無視できないAPIエラー設計

3339 ワード

多くのC++開発者にとって、API設計はその優先度リストの中で3位または4位になる可能性があります.多くの開発者は、C++を使用して元の機能と制御権を得る傾向があります.そのため、パフォーマンスと最適化の考え方は、これらの開発者の80パーセントを占めています.
もちろん、各C++開発者はヘッダファイル設計の各方面を考慮しているが、API設計はヘッダファイル設計だけではない.実際、開発者一人一人がAPIの設計において、公共向けでも内部向けでも、多くのメンテナンスコストを節約し、スムーズなアップグレードパスを提供し、お客様の面倒を節約できるため、いくつかの助けを与えることを強くお勧めします.
以下に挙げた多くの間違いは、私自身の経験とMartin Reddyの素晴らしい本「C++API Design」(私が強く推薦した本)から学んだものの結合です.本当にC++APIの設計を深く理解したい場合は、Martin Reddyの本を読んで、次のリストをより多くのリストとして使用してコード審査を強制する必要があります.

エラー#1:APIをネーミングスペースに入れない
なぜこれは間違いですか?
  どのコードライブラリ、特に外部APIを使用するか分からないためです.API機能をネーミングスペースに制限しないと、システムで使用されている他のAPIと名前が競合する可能性があります.
 例えば、非常に簡単なAPIとそのクライアントクラスを考えてみましょう.
//API - In Location.h
class vector
{
public:
  vector(double x, double y, double z);
private:
  double xCoordinate;
  double yCoordinate;
  double zCoordinate;
};
//Client Program
#include "stdafx.h"
#include "Location.h"
#include 
using namespace std;
int main()
{
  vector myVector;
  myVector.push_back(99);
  return 0;
}

このクラスを同時にstd::vectorのプロジェクトで使用しようとすると、コンパイラがクライアントコード参照のベクトルがstd::vectorもlocationであることを決定できないため、エラーが発生します.hで定義したvectorオブジェクト.
どうやってこの問題を解決しますか?
 APIは常にカスタムネーミングスペースに配置されます.たとえば、次のようになります.
//API
namespace LocationAPI
{
  class vector
  {
  public:
    vector(double x, double y, double z);
  private:
    double xCoordinate;
    double yCoordinate;
    double zCoordinate;
  };
}

別の方法は、すべての共通APIシンボルに一意のプレフィックスを追加することである.この約束に従うと、vectorではなくクラス「lvector」を呼び出します.このメソッドはOpenGLとQTに使用されます.
私から見れば、純粋なCのAPIを開発しているなら、それは理にかなっている.すべての共通記号がこの唯一の命名規則に合致していることを確認することは、もう一つの悩ましい問題です.C++を使用している場合は、ネーミングスペースでAPI機能のみをグループ化し、コンパイラに煩雑なタスクを完了させる必要があります.
また、機能グループ化のためにネストされたネーミングスペースを使用するか、共通APIと内部APIを分離することを強くお勧めします.良い例は、ネストされたネーミングスペースを自由に使用できるBoostライブラリです.たとえば、ルート「boost」ネーミングスペースでは、boost::variantはBoost Variant APIの共通シンボルを含み、boost::detail::variantはAPIの内部詳細を含む.

エラー#2:共通APIヘッダのグローバル範囲に「using namespace」を含める
なぜこれは間違いですか?
これにより、参照されるネーミングスペース内のすべてのシンボルがグローバルネーミングスペースで表示され、ネーミングスペースを使用するメリットが最初に相殺されます.
その他:
  • ヘッダファイルの使用者は、ネーミングスペースの含むことを取り消すことはできません.そのため、彼らは決定を使用してあなたのネーミングスペースを使用することを余儀なくされます.これは望ましくありません.
  • 名前空間がまず解決しなければならない衝突の可能性を大きく増やしました.
  • 新しいバージョンのライブラリを導入すると、プログラムの作業バージョンがコンパイルできない可能性があります.新しいバージョンで導入された名前が、アプリケーションが別のライブラリから使用している名前と競合している場合に発生します.
  • コードの「using namespace」セクションは、ヘッダを含むコードに現れる点から有効になります.これは、それ以前に現れたコードが、その点の後に現れたコードと区別される可能性があることを意味します.

  • どうやってこの問題を解決しますか?
  • 1.使用するネーミングスペース宣言をヘッダファイルに配置しないでください.ヘッダファイルを作成するために名前空間オブジェクトが必要な場合は、ヘッダファイルに完全限定名(std::cout、std::stringなど)を使用します.
  • //File:MyHeader.h:
    class MyClass
    {   
    private:
        Microsoft::WRL::ComPtr _parent;
        Microsoft::WRL::ComPtr _child;
    }

  • 2.上記の推奨#1がコードの混乱を引き起こす場合-ヘッダファイルで定義されたクラスまたはネーミングスペースに「using namespace」の使用を制限します.もう1つの選択肢は、次のようにヘッダファイルに範囲別名を使用することです.
    //File:MyHeader.h:
    class MyClass
    {
    namespace wrl = Microsoft::WRL; // note the aliasing here !
    private:
    wrl::ComPtr _parent;
    wrl::ComPtr _child;
    }
    C++ヘッダファイルに関するその他の質問については、投稿「C++ヘッダファイルの10大エラーと修正方法」を参照してください.https://www.acodersjourney.com/top-10-c-header-file-mistakes-and-how-to-fix-them/).

  •    more to read at https://mp.weixin.qq.com/s/Yyno5VNHr88BaQvMoZafVA