VS上写的C++程序,为什么在构造函数中的参数总表中,给一个字符数组形参初始化用来存放字符串,编译会显示默认实参和形参不匹配?

发布于 2022-09-07 04:32:37 字数 1661 浏览 10 评论 0

1.问题描述:
在student类中构造函数中,给形参字符数组初始化:char sname[]="no name"编译会报错,错误信息为:error C2440: “默认参数”: 无法从“const char [8]”转换为“char []”
在用定义好的类实例化对象时,传入参数处也会报错:student("朱明",86302535); ,错误信息为:error C2440: “<function-style-cast>”: 无法从“initializer list”转换为“student”
2.程序总代码如下

#include<iostream>
#include<cstring>
#pragma warning(disable:4996) //避免使用strcpy 报错
using namespace std;
class studentID {
    long value; //数据成员
public:
    studentID(long id = 0) { //函数名与类名相同,为构造函数,类中定义构造函数,id为成员函数的形参
        value = id;   //正常的参数传递
        cout << "赋给学生学号为:" << value << endl;
    }
    ~studentID() {  //析构函数
        cout << "删除学号:" << value;
    }
};
class student {
private:
    studentID id; //成员对象
    char name[20]; //未解决出错系列,实参行参为字符串传递问题
public:
    student(char sname[]="no name", long sid = 0) :id(sid) { //含析构函数的成员对象                                            
        cout << "学生姓名:" << sname << endl;
        strcpy(name,sname);
        //name = sname;
    }
    ~student() {
        cout << "删除学生姓名:" << name << endl;
    }
};
int main() {
    student("朱明",86302535); //类student的一个实例化对象
    system("pause");
    return 0;
}

总程序图片:
图片描述

编译出错信息:
图片描述

补充说明:程序原来的目的是想传入一个人名,所以用一个数组来做形参,初始化值为字符串"no name",但出现了上述错误;我试过,如果简单修改下程序,传入的是单个字符的话,则程序正常。比如构造函数初始化的地方做如下修改:char sname='a' ,当然前面数据成员也要修改为char name,其它地方也做相应修改:strcpy(name,sname)改为name = sname,实例化的地方student("朱明",86302535)改为student('x',86302535) ,则程序正常

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

茶色山野 2022-09-14 04:32:37

c++版藥丸...一天都沒人回答...果然沒什麼人留下來了...回答的答案也沒有人搭理...

它已經提示你了嘛, 你的字符串"朱明"的類型是const char*, 至於爲什麼是這個類型呢?

因爲c++的string literal("朱明")是不可修改, 從c++11開始就只能用以下兩種方法聲明了:

  • const char* str = "朱明";
  • const str指向具體實現中的text segment, const保護了此數據`

or

這兩者的目的都是爲了保證text segment中的數據不被修改. 原因窩在註釋中解釋了.

如果你的形參(parameter)是char *, 那麼傳進來的參數不就有了被修改text segment(這裏是string literal)"朱明")的危險, 所以爲了安全期間, c++11開始ban了這樣的方式,

當然, 你可能會有這樣的亦或:

窩明明形參(parameter)的類型是char[]不是char*呀.

其實呢, 這該c背鍋, c風格的字符串在c++裏面不是一等公民, 或者說first-class, (這裏有人會誤解或者說是因爲字符串或者函數他們不是base type, 而是derived type, 所以不能做到傳值, 不, 不是這樣的, struct同樣是derived type, 它就能傳值, derived type僅僅是composite typealias, 和first-class是無關的.

換而言之, 它不能作爲參數傳遞, 再換而言之, 它不能在傳參時進行深拷貝, 它能做的只是傳指針, 同樣的道理, 如果你想將函數傳遞, 在c語法裏面也只能傳函數指針, c++11開始能用struct來模擬lambda實現真正傳遞函數的功能.

好, 饒了一圈, 回答剛剛那個問題, 現在你應該明白了, 你這裏的形參char[]不得不退化成char*了, 其實vs的提示也暗示你這個信息了. 你的解決辦法有這麼幾種:

  1. 只用std::string/std::wstring
  2. 形參: 改成const char*/char const *

其實很早以前人們就發現text segment在這種情況下被修改會很危險, 但是c這貨一直不高興寫進標準來規定, 不過posix倒是弄了個strdup(3), 然後c才也跟着糊了個出來, 貌似posix不嚴格要求帶error code, 後來把may改成shall了. 那麼cppreference的表述就出錯了...或許窩該去改下cppreference...更新: 改好了...

所以跟我大聲唱:

Pointer is shit, C is shit.

Update:

補充下標準中(n4741)的wording:

clipboard.png

diff在這裏可以看到
http://www.open-std.org/jtc1/...

甚是思念 2022-09-14 04:32:37

这个代码本身的编译执行是没有错误的, (在我这个默认的初始编译器环境下), 但是, 在你的环境下, 有错误, 可能是因为这个原因. C2440 can occur because of conformance changes to the compiler in Visual Studio 2015 Update 3.

根据这个错误描述文档, 我打开了/Zc:strictStrings这个编译器选项, 才会出现你所说的错误, 所以, 你那里应该是默认开启了那个选项, 根据上面的链接.

你这个代码的问题就是类型转化的问题, 使用char sname[]="no name", 如果程序在运行时, 修改了sname字符数组的内容, 会出问题, 如果没有修改, 就不会有问题. 但是在写代码中, 这个是需要注意的.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文