I am making a set of derived classes for an assignment. I am instructed to use char arrays (c-strings). When I compile I keep getting the error:
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
I am fairly certain that my problem is originating up where I try to set the instance variable Name to the argument sent in. Here is my code with comments in where I believe the problems may be.
#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;
}
The proper syntax would be Business bs1(1,businessName1);
. If you want to use =
, you can also use copy intialization Business bs2 = Business(2,businessName2);
.
The former is known as direct initialization. They aren't exactly the same thing though, see Is there a difference in C++ between copy initialization and direct initialization? for in-depth information.
In Business bs1 = (1,businessName1);
the 1
and array businessName1
are separated by the comma operator. The comma operator evaluates the first operand, i.e. 1
and throws away the results and returns the value of the second operand, which is an array in your case. In other words, your code is the equivalent of Business bs1 = businessName1;
. This is why the error message says it cannot convert a char[10]
to a Business
object.
Change the first line that produces an error to Business bs1(1,businessName1);
and the rest similarly. That's the C++ idiom for initialization of a class instance on the stack.
Business bs2 = Business(2,businessName2);
as suggested by Jesse Good is, I'd argue, a Java idiom that is poor practice in C++. It's slower because there are two implicit constructor calls and one copy constructor call, as opposed to the single constructor call in Business bs1(1,businessName1);
. In this case there is another trap: you have not defined a copy constructor for the Business
type, which means that the compiler will create one for you that does a shallow copy. bs2.name
will end up a pointer to memory that isn't necessarily correctly freed when bs2
goes out of scope--a classic memory leak.
The corresponding C++ idiom is instead to construct a new object on the heap, then assign its address to a pointer: Business *bs2 = new Business(2,businessName2);
.
There's another problem with your code. Generally, it's also bad style to assign arrays by name in C or C++ (and remember, statically allocated strings like char theName[]
are just a special kind of array). Look at the definition of getName()
in Person
:
void getName(char theName[])
{ theName = name; }
This is assigning the array names (which are not exactly pointers, but close cousins), not copying the contents of one string to another. In printBal()
you then write
char name[80];
getName(name);
When getName()
executes it binds printBal()
's local variable name
to the parameter theName
. So far, so good, although the variable names you choose could be a little less confusing. :) But then the body of getName()
executes and assigns the address of the private instance variable name
to theName
(which is the name of an array--again, a special kind of pointer). When getName()
returns, there's no permanent change to the local variable name
in printBal()
. The correct way to write Person::getName()
would be with strcpy()
, the way you wrote the second Person
constructor:
void getName(char theName[])
{ strcpy(theName,name); }
来源:https://stackoverflow.com/questions/16179592/error-conversion-to-non-scalar-type