您的位置:首页 > 编程语言 > C语言/C++

C++学习笔记

2013-10-20 01:07 302 查看
C++学习笔记
1、explicit关键字的用法:

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来修饰。

  下面是一个小例子: 

class ClxTest

{

 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来修饰这个变量,所有问题就迎刃而解了。

  下面是修改过的代码:

class ClxTest

{

 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修饰的函数里面也能被修改。

3、超类方法有默认参数:

子类和超类都可以有不同的默认参数,但是使用的参数依赖于变量的声明类型,而不是底层的对象,例子如下:

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++中,不能继承默认参数,如果一定要有默认的话,父类和子类的默认参数必须是一样的,这样才不会出现问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息