C++学习笔记
来源:互联网 发布:淘宝网模特 编辑:程序博客网 时间:2024/06/10 07:10
C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?
如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:
- class MyClass
- {
- public:
- MyClass( int num );
- }
- //.
- MyClass obj = 10; //ok,convert int to MyClass
在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:
- MyClass temp(10);
- MyClass obj = temp;
上面的所有的C++ explicit关键字相关的操作即是所谓的"隐式转换"。
如果要避免这种自动转换的功能,我们该怎么做呢?嘿嘿这就是关键字explicit的作用了,将类的构造函数声明为"显式",也就是在声明构造函数的时候前面添加上explicit即可,这样就可以防止这种自动的转换操作,如果我们修改上面的MyClass类的构造函数为显式的,那么下面的代码就不能够编译通过了,如下所示:
- class MyClass
- {
- public:
- explicit MyClass( int num );
- }
- //.
- MyClass obj = 10; //err,can't non-explict convert
总结:通过使用explicit关键字来标记构造函数,可以禁止这个类的隐式转换,而且explicit关键字只能放在类定义中,而且只适用于仅有一个参数的构造函数。
2、mutable关键字的用法:
mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。
下面是一个小例子:
{
public:
void Output() const;
};
void ClxTest::Output() const
{
cout << "Output for test!" << endl;
}
void OutputTest(const ClxTest& lx)
{
lx.Output();
}
类ClxTest的成员函数Output是用来输出的,不会修改类的状态,所以被声明为const的。
函数OutputTest也是用来输出的,里面调用了对象lx的Output输出方法,为了防止在函数中调用其他成员函数修改任何成员变量,所以参数也被const修饰。
如果现在,我们要增添一个功能:计算每个对象的输出次数。如果用来计数的变量是普通的变量的话,那么在const成员函数Output里面是不能修改该变量的值的;而该变量跟对象的状态无关,所以应该为了修改该变量而去掉Output的const属性。这个时候,就该我们的mutable出场了——只要用mutalbe来修饰这个变量,所有问题就迎刃而解了。
下面是修改过的代码:
{
public:
ClxTest();
~ClxTest();
void Output() const;
int GetOutputTimes() const;
private:
mutable int m_iTimes;
};
ClxTest::ClxTest()
{
m_iTimes = 0;
}
ClxTest::~ClxTest()
{}
void ClxTest::Output() const
{
cout << "Output for test!" << endl;
m_iTimes++;
}
int ClxTest::GetOutputTimes() const
{
return m_iTimes;
}
void OutputTest(const ClxTest& lx)
{
cout << lx.GetOutputTimes() << endl;
lx.Output();
cout << lx.GetOutputTimes() << endl;
} 计数器m_iTimes被mutable修饰,那么它就可以突破const的限制,在被const修饰的函数里面也能被修改。
class A{public:virtual void go(int i = 2){ cout << "A's go with param " << i << endl;}};class B : public A{public:virtual void go(int i = 7){ cout << "B's go with param " << i << endl;}};int main(){A a;B b;A *p = &b;a.go();b.go();p->go();}输出结果为:
原因分析:C++把默认参数与指示对象的变量类型绑定在一起,而不是与对象本身绑定,也是由于这个原因,在C++中,不能继承默认参数,如果一定要有默认的话,父类和子类的默认参数必须是一样的,这样才不会出现问题
- C++/C学习笔记
- 【C/C++】STL学习笔记
- C/C学习笔记/导言
- C/C学习笔记/结构
- 【c/c++】学习笔记1
- C学习笔记1
- TPC-C学习笔记
- c语言学习笔记
- C语言学习笔记
- C语言学习笔记
- 学习笔记之c
- C#-学习笔记
- Objective-C学习笔记
- C++PRIMER学习笔记
- C学习笔记
- C 学习笔记
- C/C++学习笔记
- 1.C学习笔记
- 二叉树的常用操作(C++实现)
- [转]转的别人的一篇文章:python模块之samba
- oracle中按行查找指定记录数
- CXGRID增加非绑定数据源字段,实现勾选功能
- 关于定时器操作的一些补充
- C++学习笔记
- 编写 Objective-C 代码
- DOS批处理高级教程(还不错)
- Oracle DB 使用子查询来解决查询
- 输入输出函数 Input/Output with files
- java的几种模式!
- 空指针赋值分区
- 接下来的一个星期
- java的几种发展!