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

C++ 学习之函数重载、基于const的重载

2016-02-05 11:29 323 查看
今天阅读boost源码发现一个奇怪的问题(enable_shared_from_this.hpp源码)

#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

//
//  enable_shared_from_this.hpp
//
//  Copyright 2002, 2009 Peter Dimov
//
//  Distributed under the Boost Software License, Version 1.0.
//  See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt //
//  http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html //

#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>

namespace boost
{

template<class T> class enable_shared_from_this
{
protected:

enable_shared_from_this() BOOST_NOEXCEPT
{
}

enable_shared_from_this(enable_shared_from_this const &) BOOST_NOEXCEPT
{
}

enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_NOEXCEPT
{
return *this;
}

~enable_shared_from_this() BOOST_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
{
}

public:

shared_ptr<T> shared_from_this()
{
shared_ptr<T> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}

shared_ptr<T const> shared_from_this() const
{
shared_ptr<T const> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}

public: // actually private, but avoids compiler template friendship issues

// Note: invoked automatically by shared_ptr; do not call
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
{
if( weak_this_.expired() )
{
weak_this_ = shared_ptr<T>( *ppx, py );
}
}

private:

mutable weak_ptr<T> weak_this_;
};

} // namespace boost

#endif  // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
请注意,shared_from_this有两个版本,其中一个后面有const,这时心中顿生疑问,难道这样也可以重载?瞬间疑惑,写个例子吧

#include "stdafx.h"
#include <iostream>
#include <deque>

using namespace std;

class Test
{
public:
Test (int t):m_int(t) {}
int getInt(int t)
{
return m_int;
}
int getInt( int t) const
{
return m_int*2;
}

private:
int m_int;
};

void main()
{
Test t(10);
int ti = t.getInt(0);

return ;
}
编译一下确实可以编译的过去,调试一下发下ti=10,也就是说成功调用了非const版本的成员函数,这时心中更加疑虑,那个带const怎么调用呀?百思不得其解就上网搜了下,果然C++支持这种写法,调用带const的成员函数的方式为:

const Test *p = new Test(10);
int ti = p->getInt(0);

调试ti的值为20(当然用引用的方法也是一样的)

这里是进行了函数重载,如果去掉非const的那个函数,用非const类型一样可以直接调到带const的那个函数.

下面是从网上得到的资料

函数重载

函数重载的定义是:在相同的作用域中,如果函数具有相同名字而仅仅是形参表不同,此时成为函数重载。注意函数重载不能基于不同的返回值类型进行重载。

注意函数重载中的“形参表”不同,是指本质不同,不要被一些表象迷惑。main函数不能被重载。

下面三组定义本质是相同的,不是重载:

1)int sum (int &a); 和 int sum (int &);

2)  int sum (int a) 和 int sum (const int a);

3)typedef int DD;

     int sum(int a); 和 int sum (DD a);

其中第二个例子对于非引用传参,形参是否const是等价的。但是当使用引用传参时,有无const是不同的。使用指针传参时,指向const对象的指针和指向非const对象的指针做形参的函数是不同的。

*下面谈论一个比较恶心的问题,基于const的重载。

在类中会有这样一种重载,它是合法的。

Class A {

int function ();

int function () const;

};

可以看到在A类中,function函数是发生重载了,而且是合法的。而且在调用时,只用A类的const对象才能调用const版本的function函数,而非const对象可以调用任意一种(调用const版本的该是先转化为const对象),通常非const对象调用不是const版本的function函数。

原因是:按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在类中,由于隐含的this形参的存在,const版本的 function函数使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数。

(注:this指针是一个const指针,地址不能改,但能改变其指向的对象或者变量)

在类的成员函数后面加 const 还有(出了表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变。)什么好处呢?那就是常量(即 const)对象可以调用
const 成员函数,而不能调用非const修饰的函数。正如非const类型的数据可以给const类型的变量赋值一样,反之则不成立。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: