va_start(ap,fmt)、explicit、const

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

随着C++的学习,疑问也接连出现。


一、va_start(ap,fmt)、explicit、const

1.va_start(ap,fmt);

c 可以处理,变长的参数,比如c 的 printf 的函数原型,
int printf(const char *fmt, …); // 逗号,后面,即第二个参数是三个点
vsprintf 的函数原型:
int vsprintf(char *s, const char *fmt, va_list arg);
代码如下(示例):

#include<stdio.h>
#include<stdarg.h>
int add(int n, ...);
int main()
{
    printf("%d\n", add(4,1,2,3,4));  /* 计算 1 + 2 + 3 + 4,第一个4,是4个数的意思 */
    printf("%d\n", add(3,1,2,3,));  /* 计算 1 + 2 + 3 ,第一个3,是3个数的意思 */

    return 0;
}
int add(int n, ...)   /* 该函数返回 n  个 int 数的和,n个int,跟在第一个参数后面,依次列出*/
{
    int i, sum, tmp;
    va_list arg;              /* 定义 va_list 类型变量 arg */
    va_start(arg, n);        /* arg初始化,n 是最后一个可见的参数名字 */
    for(sum = i = 0; i < n; ++i){
        tmp = va_arg(arg, int);      /* 每一次获取一个整数,第二个类型,就是获取数的类型 */
        sum += tmp;
    }
    va_end(arg);  /* 结束之前,end 一下~~ */
    return sum;
}

2.explicit的作用

防止该类的对象直接被对应内置类型隐式转化后赋值,从而规定这个构造函数必须被明确调用。

#include <iostream>
using namespace std;
class A
{
public:
    A(int i = 5)
    {
        m_a = i;
     }
private:
    int m_a;
};
 
int main()
{
    A s;
    //我们会发现,我们没有重载'='运算符,但是却可以把内置的int类型赋值给了对象A.
    s = 10;
    //实际上,10被隐式转换成了下面的形式,所以才能这样.
    //s = A temp(10); 
    system("pause");
    return 0;
}
#include <iostream>
using namespace std;
 
class A
{
public:
    //这里用explicit关键词来修饰类构造函数.
    explicit A(int i = 5, int j = 10)
    {
        m_a = i;
        m_b = j;
    }
private:
    int m_a;
    int m_b;
};
 
int main()
{
    A s;
    //这样直接赋值,会被提示错误,因为explicit抑制隐式转换的进行
    s = 10;//这样会报错!!!
    //当然显示转换还是可以的.
    s = A(20);
 
    system("pause");
    return 0;
}

3.C++中const用法

3.1 const 修饰普通的变量

注意:const对象必须初始化,因为const对象一旦创建后,就不能对其进行赋值改变,或者说通过const对象修改
const修饰指针变量时:
  (1)只有一个const,如果const位于左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,可以指向其他的内存单元。
  (2)只有一个const,如果const位于
右侧,表示指针本身是常量,不能指向其他内存地址;指针所指的数据可以通过解引用修改。
  (3)两个const,*左右各一个,表示指针和指针所指数据都不能修改。

/****************************************************************
/****************************常量初始化**********************
****************************************************************/
const int j=43; //正确,编译时初始化
const int i=get_size();//正确,运行时初始化
const int k;  //错误,未初始化
/****************************************************************
/****************************常量初始化**********************
****************************************************************/
//普通常量
int i=42;
const int ci=i;//正确,ci=42
ci=100;//错误,不能修改
/****************************************************************
/****************************指针常量**********************
****************************************************************/
const int * cc=&i;//正确,*cc=42,但不允许通过cc修改i的值
i=60;//*cc=60
cc=&j;//正确 ,*cc=43
/****************************************************************
/****************************引用常量**********************
****************************************************************/
int i=42;
int &r1=i;
const int &r2=i;//r2也绑定了对象i,但不允许通过r2修改i的值
r1=0;           //正确;i=0
r2=0;           //错误,r2是一个常量引用
int jj=10;
r1=jj;					//正确;i=10
r2=jj;					//错误,r2是一个常量引用
const int ci=1024;
int &r2=ci;      //错误,试图让一个非常量引用指向一个常量对象
/****************************************************************
/****************************常量指针**********************
****************************************************************/
//常量指针(const pointer),指针本身定义为常量。
int errorNumb=0;
int *const curErr=&errorNumb;   //正确:curErr将一直指向errorNumb
*currErr=10;					//正确:errorNumb=10

3.2const修饰函数参数

传递过来的参数在函数内不可以改变

void testModifyConst(const int _x) {
     _x=5;   ///编译出错
}

3.3.const修饰成员函数

(1)const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外)
(2)const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量

#include <iostream>
  using namespace std;
  class Point{
      public :
   		int x;
     	void testConstFunction(int _x) const{
          x=_x;///错误,在const成员函数中,不能修改任何类成员变量
         modify_x(_x);///错误,const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量     
     }
 
     void modify_x(int _x){
         x=_x;
     }     
 };

总结

以上就是今天遇到的问题及相应的解答。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值