C++"double **"类型的实参与"double *[10]"的形参与实参类型不一致不兼容,要怎么修改?

新手求助:形参的类型后面接&是什么意思【c++吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:303,987贴子:
新手求助:形参的类型后面接&是什么意思收藏
两种情况&&
一种是:函数返回值类型
函数名(类名&&&& 形参名)
注:&和类名想结合另一种是:函数返回值类型&& 函数名(形参类型&&&& 形参名)&& 注:&和类名想结合这两天看容器都晕了&&
不是一样么……
引用……传递较大的对象作为参数时采用引用可以避免复制造成的性能损耗,如果参数不被修改可以采用const修饰
形参和实参的区分是由于值传递而出现的。由于形参与实参只是值相同而地址不同(不是同一个变量),所以两者叫做貌合神离传递指针的话,只是把指针的值(地址)以值传递的形式传给形参,所以仍然是貌合神离只用引用传递才没有形参、实参之分,所以我认为引用传递才是真正的地址传递
-5形参、实参与指针、引用毫无关系形参是函数定义时的占位符实参是函数调用是传递的值
回复:6楼这个……难道我记忆有误么?谭XX是怎么说的来着?查了一下百科,看来我记错了,误人子弟真是抱歉啊羞愧ing
登录百度帐号mfc c++初学;char *类型实参与LPCTSTR的形参不兼容怎么办 程序如下_百度知道
mfc c++初学;char *类型实参与LPCTSTR的形参不兼容怎么办 程序如下
... char *a = (char*)malloc(temp);
in.seekg(i02 + 8, ios::beg);
in.read(a, temp);
MessageBox(a);//出错 char *类型实参与LPCTSTR的形参不兼容...
我有更好的答案
MessageBox((LPCTSTR)(LPTSTR)a);请采纳。慢慢学哈。
不得 出乱码 如果是a[0]的话是出空白 a[0]跟踪到'3'这个值的
你的a ,定义为char *a =new char[1024];试试
或者MessageBoxA();如果你使用的是Unicode编码,考虑MessageBox( _t( a ) )
cs.Format(_T(&%c&), a[0]);
MessageBox(cs);这么就OK了
采纳率:62%
MessageBoxA
为您推荐:
其他类似问题
lpctstr的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。C++获取模版实参类型
如下代码:
#include &iostream&
#include &ostream&
template&class T&
class point
& typedef T value_
& point(T const& x, T
const& y) : x_(x), y_(y) {}
& point() : x_(), y_() { std::cout
"point&&()\n"; }
& T const& x() const { return x_;
& T const& y() const { return y_;
& void move_absolute(T const& x, T
const& y) {
& void move_relative(T const& dx,
T const& dy) {
template&&
class point&double&
& typedef double value_
& point(double& x, double y) :
x_(x), y_(y) {}
& point() : x_(), y_() { std::cout
"point&double& specialization\n";
& double x() const { return x_; }
& double y() const { return y_; }
& void move_absolute(double x, double y) {
& void move_relative(double dx, double dy) {
& double x_;
& double y_;
int main()
& point&short&
& point&double&
& s.move_absolute(10, 20);
& d.move_absolute(1.23, 4.56);
&如果想看模版实例化后模版实参的类型,可以包含头文件&typeinfo&,并在原有模版中,调用typeid(T).name()来获得T类型的描述字符串,字符串的确切内容取决于实现。
& 可以在上面的模版中编写以下构造函数:
point():x_(),y_(){std::cout&&"point&"&&typeid(T).name()&&"&()\n"}
不同的编译器可能的输出结果为:
point&short&()
point&double&specialization
point&s&()
point&double&specialization
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。C++ 泛型编程基础:模板通识 - 文章 - 伯乐在线
& C++ 泛型编程基础:模板通识
测试环境:Target: x86_64-linux-gnu
gcc version 5.3.1
(Ubuntu 5.3.1-14ubuntu2.1)
什么是泛型编程?为什么C++会有模板?这一切的一切都要从如何编写一个通用的加法函数说起。
很久很久以前
有一个人要编写一个通用的加法函数,他想到了这么几种方法:
使用函数重载,针对每个所需相同行为的不同类型重新实现它
int Add(const int &_iLeft, const int &_iRight)
return (_iLeft + _iRight);
float Add(const float &_fLeft, const float &_fRight)
return (_fLeft + _fRight);
int Add(const int &_iLeft, const int &_iRight){return (_iLeft + _iRight);}float Add(const float &_fLeft, const float &_fRight){return (_fLeft + _fRight);}
当然不可避免的有自己的缺点:
只要有新类型出现,就要重新添加对应函数,太麻烦
代码的复用率低
如果函数只是返回值类型不同,函数重载不能解决(函数重载的条件:同一作用域,函数名相同,参数列表不同)
一个方法有问题,所有的方法都有问题,不好维护
使用公共基类,将通用的代码放在公共的基础类里面
1、借助公共基类来编写通用代码,将失去类型检查的优点
2、对于以后实现的许多类,都必须继承自某个特定的基类,代码维护更加困难
#define ADD(a, b) ((a) + (b))
#define ADD(a, b) ((a) + (b))
不进行参数类型检测,安全性不高
编译预处理阶段完成替换,调试不便
所以在C++中又引入了泛型编程的概念。泛型编程是编写与类型无关的代码。这是代码复用的一种手段。模板则是泛型编程的基础。
模板分为了函数模板和类模板:
函数模板:代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
什么意思呢?往下看就知道了。
模板函数的格式
template&typename Param1, typename Param2,…,class Paramn&
返回值类型 函数名(参数列表)
一个简单的Add函数模板:
template &typename T& //T可是自己起的名字,满足命名规范即可
T Add(T left, T right)
return left +
int main()
Add(1, 2); //right 调用此函数是将
Add(1, 2.0); //error 只有一个类型T,传递两个不同类型参数则无法确定模板参数T的类型,编译报错
123456789101112
template &typename T& //T可是自己起的名字,满足命名规范即可&&T Add(T left, T right)&&{&&&&&&return left + right;&&}&&&&int main()&&{&&&&&&Add(1, 2); //right 调用此函数是将&&&&&&Add(1, 2.0); //error 只有一个类型T,传递两个不同类型参数则无法确定模板参数T的类型,编译报错&&&&&&return 0;&&}
对第一个函数调用,编译器生成了 int Add(int, int) 这样一个函数。
typename是用来定义模板参数关键字,也可以使用class。不过建议还是尽量使用typename,因为这个关键字是为模板而生的!
注意:不能使用struct代替typename。(这里的class不是之前那个class的意思了,所以你懂的)
当然你也可以把函数模板声明为内联的:
template &typename T&
inline T Add(T left, T right) {//…}
编译器用模板产生指定的类或者函数的特定类型版本,产生模板特定类型的过程称为函数模板实例化。(用类类型来创建一个对象也叫做实例化哦!)
模板的编译
模板被编译了两次:
实例化之前,检查模板代码本身,查看是否出现语法错误,如:遗漏分号(遗憾的是不一定能给检查的出来)
在实例化期间,检查模板代码,查看是否所有的调用都有效,如:实例化类型不支持某些函数调用
从函数实参确定模板形参类型和值的过程称为模板实参推演。多个类型形参的实参必须完全匹配。
如对这样的函数调用:
template &typename T1, typename T2, typename T3&
void fun(T1 t1, T2 t2, T3 t3)
//do something
int main()
fun(1, 'a', 3.14);
12345678910
template &typename T1, typename T2, typename T3&&&void fun(T1 t1, T2 t2, T3 t3)&&{&&&&&&//do something&&}&&int main()&&{&&&&&&fun(1, 'a', 3.14);&&&&&&return 0;&&}
编译器生成了如下这样的函数:
其中,函数参数的类型是和调用函数传递的类型完全匹配的。
类型形参转换
一般不会转换实参以匹配已有的实例化,相反会产生新的实例。
举个栗子:对如下的函数调用:
template &typename T&
T Add(T left, T right)
return left +
int Add(int left, int right)
return left +
int main()
Add(1.2, 3.4);
12345678910111213141516
template &typename T&&&T Add(T left, T right)&&{&&&&&&return left + right;&&}&&&&int Add(int left, int right)&&{&&&&&&return left + right;&&}&&&&int main()&&{&&&&&&Add(1.2, 3.4);&&&&&&return 0;&&}
即程序中已经实现过了Add函数的int版本,那么调用Add(1.2, 3.4);时,编译器不会将1.2和3.4隐式转换为int型,进而调用已有的Add版本,而是重新合成一个double的版本:
当然前提是能够生成这么一个模板函数。如果这个模板函数无法生成的话,那么只能调用已有的版本了。
编译器只会执行两种转换:
1、const转换:接收const引用或者const指针的函数可以分别用非const对象的引用或者指针来调用
2、数组或函数到指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规指针转换。数组实参将当做指向其第一个元素的指针,函数实参当做指向函数类型的指针。
template &typename T&
T Add(const T &left,const T &right)
return left +
int main()
Add(1.2, 3.4);
1234567891011
template &typename T&&&T Add(const T &left,const T &right)&&{&&&&&&return left + right;&&}&&&&int main()&&{&&&&&&Add(1.2, 3.4);&&&&&&return 0;&&}
面对这样的传参,编译器是可以完成1.2到const double &类型的转换,因为这样做是安全的。
template &typename T&
T Add(const T &left,const T &right)
return left +
int main()
Add(1.2, 3.4);
1234567891011
template &typename T&&&T Add(const T &left,const T &right)&&{&&&&&&return left + right;&&}&&&&int main()&&{&&&&&&Add(1.2, 3.4);&&&&&&return 0;&&}
完成了数组到指针的转换,因为数组在作为函数参数传递时,本身就会发生降级,形参接收到的是个指针,且指向该数组的第一个元素。
template &typename T&
int sum(T *t)
//do something
void fun()
//do something
int main()
12345678910111213141516
template &typename T&&&int sum(T *t)&&{&&&&&&//do something&&}&&&&void fun()&&{&&&&&&//do something&&}&&&&int main()&&{&&&& &&&&sum(fun);&&&&&&return 0;&&}
上例完成函数到函数指针的转换。
函数模板有两种类型参数:模板参数和调用参数。模板参数又分为模板类型形参和非模板类型形参。
模板形参名字只能在模板形参之后到模板声明或定义的末尾之间使用,遵循名字屏蔽规则。
模板形参的名字在同一模板形参列表中只能使用一次。
所有模板形参前面必须加上class或者typename关键字修饰。
注意:在函数模板的内部不能指定缺省的模板实参。
模板类型形参是模板内部定义的常量,在需要常量表达式的时候,可以使用非模板类型参数。例如:
template &typename T, int size& //size即为非模板类型参数
void sum(T (&arr)[size])
int main()
int arr[10];
sum(arr); //这里调用时,自动将10传递给size,作为数组元素个数
1234567891011
template &typename T, int size& //size即为非模板类型参数&&void sum(T (&arr)[size])&&{&&}&&&&int main()&&{&&&&&&int arr[10];&&&&&&sum(arr); //这里调用时,自动将10传递给size,作为数组元素个数&&&&&&return 0;&&}
模板形参说明:
模板形参表使用括起来
和函数参数表一样,跟多个参数时必须用逗号隔开,类型可以相同也可以不相同
模板形参表不能为空
模板形参可以是类型形参,也可以是非类型新参,类型形参跟在class和typename后
模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型或自定义类型使用方法完全相同,可用于指定函数形参类型、返回值、局部变量和强制类型转换
模板形参表中,class和typename具有相同的含义,可以互换,使用typename更加直观。但关键字typename是作为C++标准加入到C++中的,旧的编译器可能不支持。
模板函数重载
int Max(const int& left, const int & right)
return left&right? left:
template&typename T&
T Max(const T& left, const T& right)
return left&right? left:
template&typename T&
T Max(const T& a, const T& b, const T& c)
return Max(Max(a, b), c);
int main()
Max(10, 20, 30);
Max&&(10, 20); //3.用模板生成,而不是调用显示定义的同类型版本
Max(10, 20);
Max(10, 20.12);
Max&int&(10.0, 20.0); //显示告诉编译器T的类型
Max(10.0, 20.0);
1234567891011121314151617181920212223
int Max(const int& left, const int & right)&&{&&&&return left&right? left:right;&&}&&template&typename T&&&T Max(const T& left, const T& right)&&{&&return left&right? left:right;&&}&&template&typename T&&&T Max(const T& a, const T& b, const T& c)&&{&&&&&&return Max(Max(a, b), c);&&};&&int main()&&{&&&&&&Max(10, 20, 30);&&&&&&Max&&(10, 20); //3.用模板生成,而不是调用显示定义的同类型版本&&&&&&Max(10, 20);&&&&&&Max(10, 20.12);&&&&&&Max&int&(10.0, 20.0); //显示告诉编译器T的类型&&&&&&Max(10.0, 20.0);&&&&&&return 0;&&}
一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调动非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板
显式指定一个空的模板实参列表,该语法告诉编译器只有模板才能来匹配这个调用,而且所有的模板参数都应该根据实参演绎出来
模板函数不允许自动类型转换,但普通函数可以进行自动类型转换
上面的函数模板不能用来比较两个字符串,如果传递参数为字符串,返回的则是两个参数地址的比较,不是我们想要的结果。所以,又有了模板函数特化:
模板函数特化形式如下:
1、关键字template后面接一对空的尖括号
2、再接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参
3、函数形参表
在模板特化版本的调用中,实参类型必须与特化版本函数的形参类型完全匹配,如果不匹配,编译器将为实参模板定义中实例化一个实例。
举一个栗子:
template &typename T&
int cmp(const T &left, const T &right)
return left -
template &&
int cmp&const char * &&(const char * &p1, const char * &p2)
return strcmp(p1, p2);
int main()
const char *s1 = "abc";
const char *s2 = "abd";
cmp(s1, s2);
12345678910111213141516171819
template &typename T&&&int cmp(const T &left, const T &right)&&{&&&&&&return left - right;&&}&&&&template &&&&int cmp&const char * &&(const char * &p1, const char * &p2)&&{&&&&&&return strcmp(p1, p2);&&}&&&&int main()&&{&&&& &&&&const char *s1 = "abc";&&&&&&const char *s2 = "abd";&&&&&&cmp(s1, s2);&&&&&&return 0;&&}
再次强调,实参类型必须与特化版本函数的形参类型完全匹配,哪怕实参前边修饰的没有const,而模板形参中有,也不会构成特化。特化版本是对应于此模板而写的,特化版本的参数类型必须完全与模板形参相同,如上述例子中,都为const &。
template&class 形参名1, class 形参名2, …class 形参名n&
class 类名
{ … };
举个栗子:
// 以模板方式实现动态顺序表
template&typename T&
class SeqList
SeqList();
~ SeqList();
template &typename T&
SeqList &T&:: SeqList()
: _size(0)
, _capacity(10)
, _data(new T[ _capacity])
template &typename T&
SeqList &T&::~ SeqList()
delete [] _
void test1 ()
SeqList&int & sl1;
SeqList&double & sl2;
12345678910111213141516171819202122232425262728
// 以模板方式实现动态顺序表&&template&typename T&&&class SeqList&&{&&public :&&&&&&SeqList();&&&&&&~ SeqList();&&private :&&&&&&int _size ;&&&&&&int _capacity ;&&&&&&T* _data ;&&};&&template &typename T&&&SeqList &T&:: SeqList()&&&&&&: _size(0)&&&&&&, _capacity(10)&&&&&&, _data(new T[ _capacity])&&{}&&template &typename T&&&SeqList &T&::~ SeqList()&&{&&&&&&delete [] _data ;&&}&&void test1 ()&&{&&&&&&SeqList&int & sl1;&&&&&&SeqList&double & sl2;&&}
与调用函数模板形成对比,使用类模板时,必须为模板形参显式指定实参!
模板类的实例化
只要有一种不同的类型,编译器就会实例化出一个对应的类。
SeqList sl1;
SeqList sl2;
当定义上述两种类型的顺序表时,编译器会使用int和double分别代替模板形参,重新编写SeqList类,最后创建名为SeqList和SeqList的类。拒绝访问 | www.ggdoc.com | 百度云加速
请打开cookies.
此网站 (www.ggdoc.com) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(4342f11ddbfd43a1-ua98).
重新安装浏览器,或使用别的浏览器}

我要回帖

更多关于 形参与实参类型不一致 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信