2

次のシナリオを考えてみましょう: いくつかのポリモーフィック クラス:

struct iClass 
{
  virtual ~iClass(){} 
};
struct CommonClass : public iClass 
{
  char str[128];
  CommonClass() { ... }
  ...
};
struct SpecificClass : public iClass
{
  char str[32];
  SpecificClass () { ... }
  SpecificClass (SpecificClass& src) { strcpy(...); ... }
  SpecificClass (CommonClass& src) { strcpy(...); ... }
  SpecificClass (const CommonClass& src) { strcpy(...); ... }
  void foo() { ... }
};

さらに機能:

void someFunc(SpecificClass sc) { sc.foo(); } // pass by value: i want it copied!

int main ()
{
  CommonClass comCl;
  someFunc(comCl);  // <- Error: no matching function for call to 'SpecificClass::SpecificClass(SpecificClass)' NOTE: no &
  SpecificClass specCl(comCl);
  someFunc(specCl); // Works normal, but the str gets copied double times this way, isnt it?
  return 0;
}

コンパイラは、最初の関数呼び出しで CommonClass から SpecificClass への変換を許可しないのはなぜですか? そして、なぜこの奇妙なエラーメッセージが表示されるのですか? 参照なしでコピー コンストラクターを呼び出しますか? 誰かがこの問題についての洞察を共有できますか?

ところで、私はgcc 4.1.2を使用する必要があります

4

1 に答える 1

3

someFuncには type の引数が必要SpecificClassですが、 type の 1 つを指定しますCommonClass。変換コンストラクターを定義したので

SpecificClass::SpecificClass(CommonClass &)

この変換は暗黙的に実行でき、これは今のところ素晴らしいことです。

[ただし、変換コンストラクターは非 const 参照を取ることに注意してください。これは、実際に左辺値を指定するため、ここで機能します。ただし、一般的には、変換コンストラクターの引数をそのまま使用するconst CommonClass &方が通常は優れていると思います (通常、ある型から別の型への変換によって元の型が変更されることは想定されていないためです)。

ただし、次のステップで問題が発生します。新しく変換された 型のオブジェクトを の関数引数にSpecificClassコピーする必要があります。このためには、右辺値を取ることができるコピー コンストラクターが必要です (これは、一時的なものであるため、新しく変換されたオブジェクトです)。scsomeFuncSpecificClassSpecificClass

コピー コンストラクター

SpecificClass::SpecificClass(SpecificClass &)

非 const 左辺値参照を取るように宣言されているため、一時的にバインドできません。したがって、これを次のように変更する必要があります

SpecificClass::SpecificClass(const SpecificClass &)

問題を解決します。とにかく、それがコピー コンストラクターを宣言する通常の方法です。


私が気づかざるを得ないもう1つのことsomeFuncは、非常に特定のタイプのオブジェクトでのみ呼び出されることを意図した関数があることです。それでも、一般的な (基本クラス?) 型で呼び出します。明らかに、これはあなたが説明した方法で機能させることができますが、多くの点で直感に反しており、オブジェクト指向プログラミングの原則とうまく連携していません。また、「特定の」オブジェクトが「共通の」オブジェクトから実際にどのように作成されるのか、つまり、変換コンストラクターが実際に何を行うのかについても疑問に思います。直感的に、入力として与えられた「共通」オブジェクトには、「特定の」オブジェクトを作成するための「特定の」情報が欠けていると思います。

いずれにせよ、クラス階層の構造および/または の目的を再考する必要があるかもしれませんsomeFunc。ただし、これは質問で説明されている問題に直接関係するものではありません。

于 2013-06-21T07:51:54.727 に答える