4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++で手動DIしようとしたらハマった件

Posted at

 最近、DI覚えました。真に作りたい機能に集中して作れるのはとってもいいもんです。

 で、ちょっとしたCSVパーサーを作ってた時のこと。CSVを読み込むにも、ファイルからなのかWEB上からなのか、そもそも文字コードの問題もあるわけです。

 そんなことをいちいちパーサーに書きたくない。そこで、読み込み部分はIRepositoryというインターフェースにして疎結合を目指そうとしました。疎結合あるあるですね。

そんな感じでザッと書いたコードがこんな感じ。

#include <iostream>
using namespace std;


class IRepository
{
public:
    virtual string GetText() const = 0;
};

class CSVParser
{
public:
    CSVParser(const IRepository &repository){/*なんやかんや*/}
    const char *Value(int row,int col){return "なんやかんや";}
};

class TempRepo : public IRepository
{
public:
    string GetText() const {return string("ねこ,にゃーん\ncat,meow");}
};

int main(void){
    CSVParser parser(TempRepo());
    cout << parser.Value(0,1); //(1)
    return 0;
}

 具体的なパーシングは省略しましたが、適当なCSV文字列を一旦TempRepoに持たせて、その文字列のカンマや改行が適切に解釈され、(1)の部分で「にゃーん」と表示されるはず。
 しかし、この行で「式にはクラス型が必要です。」のようなエラーが出てビルドさせてくれません。つまりparserがCSVParser型と認識してないんです。

ところで、クラスを引数なしコンストラクタで初期化して使うときは()を書いてはいけません。

CSVParser parser(); //エラー
CSVParser parser; //OK

()を書くと関数宣言とみなされ、意味合いが違ってきます。

症状としては近いのですが、今回は引数ありです。うーん。

CSVParser parser = CSVParser(TempRepo());

これは通りました。

じゃ、試しにキャストしてみるか。

CSVParser parser((const IRepository &)TempRepo());

通った:innocent:

ここに強く深く刻む わすれられぬように

4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?