呼び出し元をC ++のメンバ関数で見つけることはできますか?

私はクラスを持っていて、それをクラスmyClassと呼ぶことにする

class myClass{

 //some math operations
  myClass get_difference(myClass &b)
  {
       print_operation(*this, b);
       do_something else
       return...
  }
  myClass get_sum(myClass &b)

// pseudocode 
void print_operation(const myClass *a, const myClass &b)
{
     if function == get_sum
         print a << "plus" << b;
     if function == get_difference
         print a << "minus" << b;
}

 //overload cout as well
};

私が次のように呼んだとします

myClass anObject(1,2);
myClass anotherObject(3,4);

anObject.get_sum(anotherObject);
anObject.get_difference(anotherObject);

get_sum/get_differenceは print_operation を呼び出しますが、別の出力形式が使用されるように呼び出し元を特定できるようにしたいと考えています。

Naive approach: Use switch-case Add a new parameter called "id". Give each function (the caller) an id, and use switch-case statements in print_operation.

しかし、代替手段はありますか?より洗練されたソリューションですか?

ありがとう。

0
ハハ。ありがとう。私は知らないだろう。いつもよりスマートな方法を考え出すことができる人がいます。しかし、以下の提案は非常に便利です。見つけた。 :)重要なことは:「関数は知ってはいけません。
追加された 著者 CppLearner,
これは単純なアプローチではなく、正しいアプローチです:print_operation が正しいことをするために使用できる何らかのパラメータを渡します。関数は、誰に呼び出されたのか、呼び出されたのか、それらのパラメータが与えられたのかを知ってはいけません。
追加された 著者 Andrew Marshall,
よりエレガントな - いいえ。代替 - テンプレート。ハックスタックトレース(プラットフォームに依存)。
追加された 著者 user405725,

3 答え

Cpp関数は、スタックをハックしない限り、呼び出し元が誰かを知らない。ですから、一般的に言えば、print_operationに情報(関数パラメータ、テンプレートパラメータ、データメンバ..)を渡して、どの操作を印刷するかを伝える必要があります。

だから答えはもはや洗練された解決策ではありません。

2
追加された
こんにちは。回答いただきありがとうございます。うん。しかし、この段階では、私は単純なスイッチケースソリューションに固執します。私のクラスをテンプレートで書き直すなど、今すぐ混乱しています:)ありがとう。
追加された 著者 CppLearner,

Have you considered adding a virtual const std::string& getFormatted() const in the caller?

形式が演算子に両方の引数の関数になる場合は、形式を調べるために何らかの組み合わせのテーブルを作成する必要があります。

書式が各引数の印字の長さの関数であれば(もっと簡単に)、 virtual size_t getFormatLength()const を使うことができます。

注意:print_operation()はgetFormatted()関数を持っている点を除いて呼び出し元については何も知らないが、呼び出し元はopの値に基づいて自身をフォーマットします。

これは職場でのOOP /多型です。

Andrew Marshallが上記のコメントで答えたように、OOP /カプセル化の一環として、呼び出し元の実装については何も知ってはいけません。

多態性は正しく行われ、呼び出し側から実装の詳細をカプセル化しようとする必要があります。

class myClass
{
  public:
    virtual std::string getFormatted( const std::string& op ) const = 0;
};

class A : public myClass
{
  public:
    virtual std::string getFormatted( const std::string& op ) const
    {
     //switch on the value of op or the length of op, etc...

      return std::string( "this, formatted according to class A specs and op" );
    }
};

class B : public myClass
{
  public:
    virtual std::string getFormatted( const std::string& op ) const
    {
     //switch on the value of op or the length of op, etc...

      return std::string( "this, formatted according to class B specs and op" );
    }
};

void print_operation(const myClass &a, const myClass &b )
{
  std::string op;

  if ( function == get_sum ) {
    op = "plus";
  } else if ( function == get_difference ) {
    op = "minus"; 
  }
  std::cout << a.getFormatted( op ) << op << b.getFormatted( op );
}
1
追加された
@CppLearnerは、myClassの特定のインスタンスに、フォーマットがどのように見えるかを指定する機会を与えます。これは、実装がmyClassのサブクラスに存在するためです。 "しかし、私は別の出力形式が使用されるように呼び出し元を判断できるようにしたい"と言うとき、仮想getFormat()を持つと、呼び出し側に出力形式を指定する機会が与えられます。
追加された 著者 kfmfe04,
@CppLearner - フィードバックのために - C + +であなたの冒険と幸運!
追加された 著者 kfmfe04,
getFormatが何をするのか分かりませんか?それを少し拡大する気がしますか?ありがとう!
追加された 著者 CppLearner,
ありがとうkfmfe04私はあなたが継承とポリに言及しているかどうか尋ねるつもりでした。ありがとう。それは本当に役立ちます。
追加された 著者 CppLearner,

問題は、発信者が誰であるかを知ることにまでは至っていません。データをフォーマットするためのさまざまな方法を実際に定義したいと思っているように聞こえますし、異なる発信者のために必要なフォーマッターが異なるかもしれません。

.NETの教訓を踏まえて、 IFormattable.ToString をクリックします。この例では、書式文字列を使用してさまざまな出力書式を区別しています。あなたの場合は、整数、列挙型、または適切なもので定義することができます。

1
追加された
こんにちは。そのとおりです。異なる発呼者のための異なるフォーマット。私はそれを調べます。ありがとう。
追加された 著者 CppLearner,