web-dev-qa-db-ja.com

Visual C ++で「適切なデフォルトコンストラクタが利用できません」エラー

わかりません。コードを3時間見つめていましたが、問題がわかりません。

私が作成しているTwoDayPackageというクラスは、Packageというクラスから派生しています。

これが私がコンストラクターを定義した方法です:

    TwoDayPackage(string, string, string, string, int, string, string, string, string, int, float, float, float);

これが私がコンストラクターを実装する方法です:

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat)
{
Package::Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost);
flatRate = flat;
}

これが私のメイン関数での使用方法です。

TwoDayPackage pack2(senderName, senderAddress, senderState, senderCountry, senderZIP, receipientName, receipientAddress, receipientState, receipientCountry, receipientZIP, weight, cost, flat);

私の議論リストがかなり長いことを私は知っています、それには理由があります。ありがとう。

15
chustar

使用する必要があります:

TwoDayPackage::TwoDayPackage(string sName, string sAddress, string sState, string  sCountry, int sZIP, string rName, string rAddress, string rState, string rCountry, int rZIP, float weight, float cost, float flat)
 :Package(sName, sAddress, sState, sCountry, sZIP, rName, rAddress, rState, rCountry, rZIP, weight, cost)
  {
    flatRate = flat;
   }
23
dirkgently

デフォルトのctorは、引数なしで呼び出すことができるctorです。少なくともこのコードでは、1つはありません。デフォルトのctorにも署名があります

ClassName::ClassName();

または、すべての引数にデフォルトが必要です。

とはいえ、構文に関するDirkの指摘は正しいです。親クラスctorを呼び出す場合は、そのコロンの後に呼び出す必要があります。


@dirkgentlyの答えは正しい構文を示していますが、少し拡張してみましょう。 2つのクラスがあります

public class Package {
    // ...
    Package( /* that horrible ctor arg list */){/*...*/}
    // ...
}

public class TwoDayPackage : public Package {
    // ...
    TwoDayPackage(/* another horrible ctor */);  // declaration only
    // ...
}

それからあなたはそれを定義するためにやって来ます

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
                             string sState, string sCountry, 
                             int sZIP, string rName, 
                             string rAddress, string rState, 
                             string rCountry, int rZIP, 
                             float weight, float cost, float flat)
{

     Package::Package(sName, sAddress, sState, sCountry, sZIP, 
                      rName, rAddress, rState, rCountry, rZIP, 
                      weight, cost);
     flatRate = flat;
}

...しかし、それは機能しませんか?どうして?基本的に、C++に言っていることは意味をなさないため、Package::Packageは、スーパークラスのctorに名前を付けるだけで、何もしていません。 new演算子を使用して、クラスPackageの新しいオブジェクトを作成できます。

     Package foo = new
         Package::Package(sName, sAddress, sState, sCountry, sZIP, 
                          rName, rAddress, rState, rCountry, rZIP, 
                          weight, cost);

しかし、それはまだあなたがやりたいことではありません。 wantは、その引数リストを使用してTwoDayPackageのパッケージ部分を構築するようにC++に指示することです。コンパイラーは親クラスが何であるかをすでに知っているため、完全修飾名を付ける必要はありません。

子ctorに値を割り当てることもできますが、コンパイラーが「ウェルへの複数回のトリップ」のコードを生成するため、非効率的です。したがって、Dirkが示したように、C++には、初期化子がコロンの後に配置される特別な構文があります。

もう1つ、とにかくフラットにパラメータを割り当てるだけなので、次のように言うことができます。

TwoDayPackage::TwoDayPackage(string sName, string sAddress, 
                             string sState, string sCountry, 
                             int sZIP, string rName, 
                             string rAddress, string rState, 
                             string rCountry, int rZIP, 
                             float weight, float cost, float flat) :
    Package(sName, sAddress, sState, sCountry, sZIP, 
            rName, rAddress, rState, rCountry, rZIP, weight, cost),
    flatRate(flat) 
{
}

詳細については、C++の このセクション FAQ Lite)を確認してください。

22
Charlie Martin

答えは dirkgently のそれです。説明はC++での初期化シーケンスです。

クラスを構築するときは、すべての基本クラスが最初に構築されます。初期化リストでコンストラクターを呼び出すと、適切なコンストラクターが呼び出されます。基本クラスが初期化リストに表示されない場合は、デフォルトで作成されます。これはすべて、コンストラクターブロック(中括弧)に入る前に発生します。