C++中的嵌套类和局部类介绍

1.嵌套类

我在看C++中关于线程的源代码的时候,看到了类里面嵌套了类,不是很明白啥是嵌套类,接下来就写写嵌套类。
我把C++中关于线程的源代码,贴在文章的末尾。
首先在这里写一下嵌套类的样子:

class person{
	int age;
	int sex;
	void work();
	void car();
	
	class handsome{
		int Age;
		int Sex;
		void work();
		void car();
	};	
};

1.1啥是嵌套类

大概形式:就是一个类中定义了另外一个类

1.2 我的疑惑

  • 这样的形式有什么作用?
  • 有什么样的作用?
    1、嵌套类可以直接访问外围类中的static成员变量。
    2、嵌套类可以通过引用,指针,或者对象来访问外围类的成员,不管该成员是public,private,protected。
    3、 嵌套类被private修饰的时候就不能在用户代码中被定义对象,因为是private的
    4 、外围类对嵌套类的非public成员没有访问权限,对public成员具有访问权限
    5 、外围类不能直接访问嵌套类的public静态成员,必须加上限定符。
  • 和分别定义的类有什么区别?
  • 主要用在什么地方?
    上面就是我第一次看到嵌套类时的一些疑问,接下来通过查找资料解答自己的疑惑。

1.2.1 嵌套类的作用域

嵌套类就是可以在一个类中定义另一个类,这个被嵌套的类的作用域就只在它的上一级类中,换句话说就是:嵌套类的名字只有外围类可见。
案例如下:

#include <iostream>
using namespace std;

class c1{
public:
    int a;
    void foo();
    class c2{   //这里的类的名字叫c2
    public:
        int a;
        void foo();
    } b;   //这里的b是类c2的实例化的名称
};
void c1::foo(){
    a = 1;
}
void c1::c2::foo(){
    a = 2;
}
int main(){
    class c1 f;
    f.foo();
    f.b.foo();
    cout << f.a << endl;      //输出为 1
    cout << f.b.a << endl;    //输出为2
    return 0;
}

其实在C语言中也有类似的用法,在一个结构体中嵌套另一个结构体,或者在一个结构体中嵌套一个union 。我们还知道,C 语言中被嵌套的结构体或union 通常是匿名的。在C++中也是可以的,我们可以在一个类中嵌套另外一个匿名类。不过,匿名类的成员函数只能在类的声明中同时定义,因为这个类没有名称,我们没法在外部指代它。
案例如下:

class c3{
public:
    int a;
    void foo() {a = 3;}
    class{          //这里的类是没有名称的,所以叫做匿名类
    public:
        int a;
        void foo() {a = 4;}
    } b;  //这里的b是匿名类的实例化
};
 
int main(){
    class c3 ff;
    ff.foo();
    ff.b.foo();
    cout << ff.a << endl;   //输出为3
    cout << ff.b.a << endl;  //输出为4
    return 0;
}

2.局部类

2.1 啥是局部类

所谓局部类,就是定义在一个函数内部的类,这个类只能在这个函数内部使用。
案例如下:

int main(){
    class c4{
    public:
        int a;
        void foo() {a = 4;}
    };
    class c4 ff;
    ff.foo();
    cout << ff.a << endl;  输出为4
    return 0;
}

通常,嵌套类和局部类的所有成员变量我们都会声明为共有的。因为这两种类只在很小的范围内使用,没有必要通过定义接口来隐藏内部的信息。所以,可以把 class 改换成 struct,这样就可以不写public 了,因为struct内部的成员变量都是公有的。

3.函数是不能嵌套的

3.1 函数是不能嵌套的,比如下面的例子是无法编译通过的

int main(){
    void foo() { cout << "WRONG";};
    foo();
}

改成下面这样就可以了

void foo() { cout << "WRONG";};
int main(){
    foo();
}

3.2 操作符重载模拟局部函数

我们可以通过一些变通的方法来模拟出一个局部函数来。具体来说就是通过重载一个类的operator () 方法来模拟一个函数调用。
案例如下:

int main(){
    struct{
        void operator () ( void ){
            cout << "HELLO" << endl;
        }
        int operator() (int a, int b){
            return a + b;
        }
    } foo;
    foo();
    cout << foo(1, 2);
}

附录:thread类的源码

// <thread> -*- C++ -*-

// Copyright (C) 2008-2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file include/thread
 *  This is a Standard C++ Library header.
 */

#ifndef _GLIBCXX_THREAD
#define _GLIBCXX_THREAD 1

#pragma GCC system_header

#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else

#include <chrono>
#include <functional>
#include <memory>
#include <cerrno>
#include <bits/functexcept.h>
#include <bits/functional_hash.h>
#include <bits/gthr.h>

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @defgroup threads Threads
   * @ingroup concurrency
   *
   * Classes for thread support.
   * @{
   */

  /// thread
  class thread         //thread源码开始的地方
  {
  public:
    // Abstract base class for types that wrap arbitrary functors to be
    // invoked in the new thread of execution.
    struct _State
    {
      virtual ~_State();
      virtual void _M_run() = 0;
    };
    using _State_ptr = unique_ptr<_State>;

    typedef __gthread_t			native_handle_type;

    /// thread::id
    class id                //这是thread的嵌套类,名字叫做id
    {
      native_handle_type	_M_thread;

    public:
      id() noexcept : _M_thread() { }

      explicit
      id(native_handle_type __id) : _M_thread(__id) { }

    private:
      friend class thread;
      friend class hash<thread::id>;

      friend bool
      operator==(thread::id __x, thread::id __y) noexcept
      {
	// pthread_equal is undefined if either thread ID is not valid, so we
	// can't safely use __gthread_equal on default-constructed values (nor
	// the non-zero value returned by this_thread::get_id() for
	// single-threaded programs using GNU libc). Assume EqualityComparable.
	return __x._M_thread == __y._M_thread;
      }

      friend bool
      operator<(thread::id __x, thread::id __y) noexcept
      {
	// Pthreads doesn't define any way to do this, so we just have to
	// assume native_handle_type is LessThanComparable.
	return __x._M_thread < __y._M_thread;
      }

      template<class _CharT, class _Traits>
	friend basic_ostream<_CharT, _Traits>&
	operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
    };

  private:
    id				_M_id;

  public:
    thread() noexcept = default;
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 2097.  packaged_task constructors should be constrained
    thread(thread&) = delete;
    thread(const thread&) = delete;
    thread(const thread&&) = delete;

    thread(thread&& __t) noexcept
    { swap(__t); }

    template<typename _Callable, typename... _Args>
      explicit 
      thread(_Callable&& __f, _Args&&... __args)
      {
#ifdef GTHR_ACTIVE_PROXY
	// Create a reference to pthread_create, not just the gthr weak symbol.
	auto __depend = reinterpret_cast<void(*)()>(&pthread_create);
#else
	auto __depend = nullptr;
#endif
        _M_start_thread(_S_make_state(
	      std::__bind_simple(std::forward<_Callable>(__f),
				 std::forward<_Args>(__args)...)),
	    __depend);
      }

    ~thread()
    {
      if (joinable())
	std::terminate();
    }

    thread& operator=(const thread&) = delete;

    thread& operator=(thread&& __t) noexcept
    {
      if (joinable())
	std::terminate();
      swap(__t);
      return *this;
    }

    void
    swap(thread& __t) noexcept
    { std::swap(_M_id, __t._M_id); }

    bool
    joinable() const noexcept
    { return !(_M_id == id()); }

    void
    join();

    void
    detach();

    thread::id
    get_id() const noexcept
    { return _M_id; }

    /** @pre thread is joinable
     */
    native_handle_type
    native_handle()
    { return _M_id._M_thread; }

    // Returns a value that hints at the number of hardware thread contexts.
    static unsigned int
    hardware_concurrency() noexcept;

  private:
    template<typename _Callable>
      struct _State_impl : public _State
      {
	_Callable		_M_func;

	_State_impl(_Callable&& __f) : _M_func(std::forward<_Callable>(__f))
	{ }

	void
	_M_run() { _M_func(); }
      };

    void
    _M_start_thread(_State_ptr, void (*)());

    template<typename _Callable>
      static _State_ptr
      _S_make_state(_Callable&& __f)
      {
	using _Impl = _State_impl<_Callable>;
	return _State_ptr{new _Impl{std::forward<_Callable>(__f)}};
      }
#if _GLIBCXX_THREAD_ABI_COMPAT
  public:
    struct _Impl_base;
    typedef shared_ptr<_Impl_base>	__shared_base_type;
    struct _Impl_base
    {
      __shared_base_type	_M_this_ptr;
      virtual ~_Impl_base() = default;
      virtual void _M_run() = 0;
    };

  private:
    void
    _M_start_thread(__shared_base_type, void (*)());

    void
    _M_start_thread(__shared_base_type);
#endif
  };

  inline void
  swap(thread& __x, thread& __y) noexcept
  { __x.swap(__y); }

  inline bool
  operator!=(thread::id __x, thread::id __y) noexcept
  { return !(__x == __y); }

  inline bool
  operator<=(thread::id __x, thread::id __y) noexcept
  { return !(__y < __x); }

  inline bool
  operator>(thread::id __x, thread::id __y) noexcept
  { return __y < __x; }

  inline bool
  operator>=(thread::id __x, thread::id __y) noexcept
  { return !(__x < __y); }

  // DR 889.
  /// std::hash specialization for thread::id.
  template<>
    struct hash<thread::id>
    : public __hash_base<size_t, thread::id>
    {
      size_t
      operator()(const thread::id& __id) const noexcept
      { return std::_Hash_impl::hash(__id._M_thread); }
    };

  template<class _CharT, class _Traits>
    inline basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
    {
      if (__id == thread::id())
	return __out << "thread::id of a non-executing thread";
      else
	return __out << __id._M_thread;
    }

_GLIBCXX_END_NAMESPACE_VERSION

  /** @namespace std::this_thread
   *  @brief ISO C++ 2011 entities sub-namespace for thread.
   *  30.3.2 Namespace this_thread.
   */
  namespace this_thread
  {
  _GLIBCXX_BEGIN_NAMESPACE_VERSION

    /// get_id
    inline thread::id
    get_id() noexcept
    {
#ifdef __GLIBC__
      // For the GNU C library pthread_self() is usable without linking to
      // libpthread.so but returns 0, so we cannot use it in single-threaded
      // programs, because this_thread::get_id() != thread::id{} must be true.
      // We know that pthread_t is an integral type in the GNU C library.
      if (!__gthread_active_p())
	return thread::id(1);
#endif
      return thread::id(__gthread_self());
    }

    /// yield
    inline void
    yield() noexcept
    {
#ifdef _GLIBCXX_USE_SCHED_YIELD
      __gthread_yield();
#endif
    }

    void
    __sleep_for(chrono::seconds, chrono::nanoseconds);

    /// sleep_for
    template<typename _Rep, typename _Period>
      inline void
      sleep_for(const chrono::duration<_Rep, _Period>& __rtime)
      {
	if (__rtime <= __rtime.zero())
	  return;
	auto __s = chrono::duration_cast<chrono::seconds>(__rtime);
	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s);
#ifdef _GLIBCXX_USE_NANOSLEEP
	__gthread_time_t __ts =
	  {
	    static_cast<std::time_t>(__s.count()),
	    static_cast<long>(__ns.count())
	  };
	while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
	  { }
#else
	__sleep_for(__s, __ns);
#endif
      }

    /// sleep_until
    template<typename _Clock, typename _Duration>
      inline void
      sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
      {
	auto __now = _Clock::now();
	if (_Clock::is_steady)
	  {
	    if (__now < __atime)
	      sleep_for(__atime - __now);
	    return;
	  }
	while (__now < __atime)
	  {
	    sleep_for(__atime - __now);
	    __now = _Clock::now();
	  }
      }

  _GLIBCXX_END_NAMESPACE_VERSION
  }

  // @} group threads

} // namespace

#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1

#endif // C++11

#endif // _GLIBCXX_THREAD

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值