2013-04-23 101 views
0

我正在爲一個賦值創建一組派生類。我被指示使用char數組(c-strings)。我編譯時不斷收到錯誤:錯誤:轉換爲非標量類型

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 

我相當肯定,我的問題是源於起來,我嘗試設置實例變量名稱在發送的說法這是我在這裏的評論代碼我相信問題可能是。

#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; 
} 

回答

5

正確的語法是Business bs1(1,businessName1);。如果你想使用=,你也可以使用複製初始化Business bs2 = Business(2,businessName2);

前者被稱爲直接初始化。儘管如此,它們並不完全相同,請參閱Is there a difference in C++ between copy initialization and direct initialization?瞭解詳細信息。

Business bs1 = (1,businessName1);1和陣列businessName1comma operator分開。逗號運算符評估第一個操作數,即1並丟棄結果並返回第二個操作數的值,這是您的案例中的一個數組。換句話說,你的代碼相當於Business bs1 = businessName1;。這就是爲什麼錯誤消息說它不能將char[10]轉換爲Business對象。

+0

哦,天哪,真不錯!哇,不敢相信我做到了。謝謝! – art3m1sm00n 2013-04-23 21:37:54

0

將產生錯誤的第一行更改爲Business bs1(1,businessName1);,其餘的相似。這是在堆棧上初始化類實例的C++習慣用法。

Business bs2 = Business(2,businessName2);正如Jesse Good所建議的,我認爲這是一個在C++中很差的Java習慣用法。這比較慢,因爲有兩個隱式構造函數調用和一個拷貝構造函數調用,與Business bs1(1,businessName1);中的單個構造函數調用相反。在這種情況下還有另外一個陷阱:你還沒有爲Business類型定義一個拷貝構造函數,這意味着編譯器會爲你創建一個做淺拷貝的構造函數。 bs2.name將結束一個指向內存的指針,當內存不在bs2超出範圍時不會被正確釋放 - 這是一種經典的內存泄漏。

相應的C++習慣用法是在堆上構建一個新對象,然後將其地址分配給一個指針:Business *bs2 = new Business(2,businessName2);

您的代碼存在另一個問題。通常,在C或C++中按名稱分配數組也是不好的方式(並且記住,像char theName[]這樣的靜態分配的字符串只是一種特殊的數組)。在Person看看getName()定義:

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

這是指定數組名稱(這是不完全的指針,但近親),而不是複製一個字符串的內容到另一個。在printBal()你再寫入

char name[80]; 
getName(name); 

getName()執行它結合printBal()的局部變量name到參數theName。到目前爲止,這麼好,儘管你選擇的變量名可能會有點混亂。 :)但是,getName()的主體執行並將私有實例變量name的地址分配給theName(這是數組的名稱 - 也是一種特殊類型的指針)。當getName()返回時,對printBal()中的本地變量name沒有永久性更改。寫Person::getName()正確的方法是與strcpy(),順便你寫的第二Person構造:

void getName(char theName[]) 
    { strcpy(theName,name); } 
+0

這個答案不正確。 1)最有可能的代碼將被優化,使兩種形式是等價的。 2)'name'是**數組**,不是指針。默認的拷貝構造函數會很好。 – 2013-04-23 22:28:40

+0

1.我認爲你不能做出如此清晰的陳述。正如你在上面給出的鏈接上討論的那樣(_是否在複製初始化和直接初始化之間存在C++差異?)顯示,存在許多複雜的邊緣情況,並且編譯器不能可靠地優化這些複製構造函數調用。我認爲這是不好的風格。 C++不是Java。 2.你是對的,但我認爲依靠默認的拷貝構造函數也是很差的C++風格;也看到我編輯的答案與原始代碼的另一個相關的問題。 – dodgethesteamroller 2013-04-23 22:58:20

+0

如果你不相信我,[quote](http://en.wikipedia.org/wiki/Copy_elision#cite_note-moreexcept-2)怎麼樣:'因此,複製初始化通常等同於直接在性能方面的初始化「。請注意,引用來自Herb Sutter的書「More Exceptional C++」。 – 2013-04-23 23:02:51

相關問題