C++ 错误:转换为非标量类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16179592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Error: Conversion to non-scalar type
提问by art3m1sm00n
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:
我正在为作业制作一组派生类。我被指示使用字符数组(c 字符串)。当我编译时,我不断收到错误:
Homework11.cpp: In function aint main()a:
Homework11.cpp:72: error: conversion from achar [10]a to non-scalar type aBusinessa requested
Homework11.cpp:73: error: conversion from achar [10]a to non-scalar type aBusinessa requested
Homework11.cpp:74: error: conversion from achar [10]a to non-scalar type aAccounta requested
Homework11.cpp:75: error: conversion from achar [10]a to non-scalar type aAccounta 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.
我相当确定我的问题出在我尝试将实例变量 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;
}
回答by Jesse Good
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);
.
正确的语法是Business bs1(1,businessName1);
. 如果要使用=
,也可以使用复制初始化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.
前者称为直接初始化。不过,它们并不完全相同,请参阅C++ 中复制初始化和直接初始化之间有区别吗?以获得深入的信息。
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.
在Business bs1 = (1,businessName1);
所述1
和阵列businessName1
由分离逗号运算符。逗号运算符评估第一个操作数,即1
丢弃结果并返回第二个操作数的值,在您的情况下它是一个数组。换句话说,您的代码相当于Business bs1 = businessName1;
. 这就是错误消息说它无法将 a 转换char[10]
为Business
对象的原因。
回答by dodgethesteamroller
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 bs1(1,businessName1);
,其余类似。这是用于在堆栈上初始化类实例的 C++ 习惯用法。
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.
Business bs2 = Business(2,businessName2);
正如 Jesse Good 所建议的那样,我认为这是一种在 C++ 中实践不佳的 Java 习语。它较慢,因为有两个隐式构造函数调用和一个复制构造函数调用,而不是Business bs1(1,businessName1);
. 在这种情况下,还有另一个陷阱:您没有为该Business
类型定义复制构造函数,这意味着编译器将为您创建一个执行浅复制的构造函数。 bs2.name
最终会得到一个指向内存的指针,当bs2
超出范围时,该指针不一定正确释放——典型的内存泄漏。
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);
.
相应的 C++ 习惯用法是在堆上构造一个新对象,然后将其地址分配给一个指针: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
:
您的代码还有另一个问题。通常,在 C 或 C++ 中按名称分配数组也是一种糟糕的风格(请记住,静态分配的字符串char theName[]
只是一种特殊类型的数组)。看看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
这是分配数组名称(它们不完全是指针,而是近亲),而不是将一个字符串的内容复制到另一个。在printBal()
你然后写
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:
当getName()
执行其绑定printBal()
的局部变量name
的参数theName
。到目前为止,一切都很好,尽管您选择的变量名称可能不那么令人困惑。:) 但是随后的主体getName()
执行并将私有实例变量的地址分配name
给theName
(这是一个数组的名称 - 再次,一种特殊类型的指针)。当getName()
返回时,有局部变量没有永久性的变化name
在printBal()
。正确的写法Person::getName()
是 with strcpy()
,你写第二个Person
构造函数的方式:
void getName(char theName[])
{ strcpy(theName,name); }