3

課題用の一連の派生クラスを作成しています。char 配列 (c-string) を使用するように指示されています。コンパイルすると、エラーが発生し続けます:

Homework11.cpp: In function âint main()â:
Homework11.cpp:72: error: conversion from âchar [10]â to non-scalar type âBusinessâ requested
Homework11.cpp:73: error: conversion from âchar [10]â to non-scalar type âBusinessâ requested
Homework11.cpp:74: error: conversion from âchar [10]â to non-scalar type âAccountâ requested
Homework11.cpp:75: error: conversion from âchar [10]â to non-scalar type âAccountâ requested

私の問題は、インスタンス変数 Name を送信された引数に設定しようとするところから発生していることはかなり確信しています。ここに、問題があると思われる場所にコメントを付けたコードを示します。

#include <iomanip>
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;

class Person{
public:
        Person() {}
        Person(char theName[]) {strcpy(name,theName);}
        void getName(char theName[]) // I think the problem may be here or in the line above
                { theName = name;}
private:
        char name[80];
 };

class Account : public Person{
public:
        Account() :accountNum(0),balance(0) {}
        Account(int actNo, char theName[])
                :Person(theName),accountNum(actNo),balance(0) {}
        void setBal(float theBalance)
                {balance = theBalance;}
        void deposit(float numDeposited)
                { balance = balance + numDeposited;}
        float withdraw(float numWithdrawn)
                { balance = balance -numWithdrawn;
                  return numWithdrawn;}
        float getBal() {return balance;}
        void printBal();
private:
        int accountNum;
        float balance;
};

 class Business : public Account{
 public:
        Business() : checkFee(0.0) {}
        Business(int actNo, char theName[])
                : Account(actNo, theName),checkFee(0.0) {}
        float withdraw(float numWithdrawn)
                {float newBalance = getBal()-numWithdrawn-checkFee;
                 setBal(newBalance);
                  return numWithdrawn;}
        void setFee(float fee) {checkFee = fee;}
 private:
        float checkFee;
};

void Account::printBal()
{
        char name[80];
        getName(name);
        cout<<setw(10)<<"Account # "<<accountNum<<setw(10)<<
              name<<setw(10)<<balance<<endl;
}


int main()
{
        char businessName1[10]="Business1";
        char businessName2[10] ="Business2";
        char regularName1[10] = "Regular1";
        char regularName2[10] = "Regular2";

       //The following 4 lines are the ones I am getting the error for
        Business bs1 = (1,businessName1);
        Business bs2 = (2,businessName2);
        Account rg1 = (1, regularName1);
        Account rg2 = (2, regularName2);

        cout<<"Intially: "<<endl;
        rg1.printBal();
        rg2.printBal();
        bs1.printBal();
        bs2.printBal();

        bs1.deposit(1000.00);
        bs2.deposit(1000.00);
        rg1.deposit(1000.00);
        rg2.deposit(1000.00);

        cout<<"----------------------------------------"<<endl;
       cout<<"After adding 1000.00 to all accounts:"<<endl;
        rg1.printBal();
        rg2.printBal();
         bs1.printBal();
        bs2.printBal();

        bs1.setFee(1.00);
        bs1.withdraw(500);
        bs2.withdraw(500);
        bs1.deposit(250);
        bs2.deposit(250);
        rg1.withdraw(500);
        rg2.deposit(500);

        cout<<"---------------------------------------"<<endl;
        cout<<"Finially:"<<endl;
        rg1.printBal();
        rg2.printBal();
        bs1.printBal();
        bs2.printBal();

        return 0;
}
4

2 に答える 2

10

適切な構文はBusiness bs1(1,businessName1);. を使用したい場合は=、コピー初期化も使用できますBusiness bs2 = Business(2,businessName2);

前者は直接初期化と呼ばれます。ただし、それらはまったく同じではありません。C++ でコピー初期化と直接初期化の間に違いはありますか? を参照してください。詳細な情報については。

Business bs1 = (1,businessName1);1配列はコンマ演算子businessName1で区切られています。コンマ演算子は、最初のオペランドを評価します。つまり、結果を破棄し、2 番目のオペランドの値を返します。これは、この場合は配列です。つまり、コードは と同等です。これが、a をオブジェクトに変換できないというエラー メッセージが表示される理由です。1Business bs1 = businessName1;char[10]Business

于 2013-04-23T21:37:14.460 に答える
1

エラーが発生する最初の行を に変更しBusiness bs1(1,businessName1);、残りも同様に変更します。これは、スタック上のクラス インスタンスを初期化するための C++ のイディオムです。

Business bs2 = Business(2,businessName2);Jesse Good が示唆しているように、C++ での実践が不十分な Java イディオムだと私は主張します。の単一のコンストラクター呼び出しとは対照的に、2 つの暗黙的なコンストラクター呼び出しと 1 つのコピー コンストラクター呼び出しがあるため、低速ですBusiness bs1(1,businessName1);。この場合、別のトラップがあります。Business型のコピー コンストラクターを定義していません。つまり、コンパイラーが浅いコピーを行うコンストラクターを作成します。 スコープ外になっbs2.nameたときに必ずしも正しく解放されないメモリへのポインタになります。これは古典的なメモリ リークです。bs2

対応する C++ のイディオムは、代わりにヒープ上に新しいオブジェクトを構築し、そのアドレスをポインターに割り当てますBusiness *bs2 = new Business(2,businessName2);

コードには別の問題があります。一般に、C や C++ で配列を名前で割り当てるのも不適切なスタイルです (また、静的に割り当てられた文字列などchar theName[]は特殊な種類の配列にすぎないことを覚えておいてください)。getName()inの定義を見てくださいPerson:

void getName(char theName[])
    { theName = name; }

これは、ある文字列の内容を別の文字列にコピーするのではなく、配列名 (厳密にはポインターではありませんが、近いものです) を割り当てています。あなたの中printBal()に書いてください

char name[80];
getName(name);

実行すると、ローカル変数がパラメータgetName()にバインドされます。これまでのところ、これで問題ありませんが、変数名を選択すると、混乱が少し少なくなる可能性があります。:) しかし、その後、 の本体が実行され、プライベート インスタンス変数のアドレスが割り当てられます(これは、配列の名前であり、特殊な種類のポインターです)。が戻ったとき、 のローカル変数に永続的な変更はありません。正しい書き方は、2 番目のコンストラクターの書き方と同じです。printBal()nametheNamegetName()nametheNamegetName()nameprintBal()Person::getName()strcpy()Person

void getName(char theName[])
    { strcpy(theName,name); }
于 2013-04-23T21:54:54.953 に答える