文章目录
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