Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

OSG的observer_ptr指针

发表于 2021-12-25

observer_ptr指针,这个指针和它的名字一样,就是用来观察指针的,可以把它想象成一个观察者,它只观察一个你给他指点的对象,但是不会影响这个对象的创建和销毁,它只是一个旁观者,但是它观察的这个对象要是被销毁了它也会知道并且自己也会被销毁。和osg::ref_ptr不同,osg::ref_ptr是用来管理指针的创建和删除的。

参考链接

  1. OSG中的observer_ptr指针,by vincent-xia.

OSG中的OpenThreads库使用帮助

发表于 2021-12-24

OpenThreads库是一个轻量级的跨平台多线程库,在2.x之前是独立发展的一个库,在2.x后并入到OSG的源码中,OSG中大量的多线程操作都是基于这个库编写的。

参考链接

  1. OpenThreads库介绍——Thread,by csxiaoshui.
  2. OpenThreads库介绍——Mutex,by csxiaoshui.
  3. OpenThreads库介绍——Block,by csxiaoshui.

CPlusPlus之volatile关键字

发表于 2021-12-22

C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier。

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。

当两个线程都要用到某一个变量且该变量的值会被改变时,应该用 volatile 声明,该关键字的作用是防止优化编译器把变量从内存装入 CPU 寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。volatile 的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值。

参考链接

  1. C/C++ 中 volatile 关键字详解,by runoob.
  2. InterlockedCompareExchange用法详解,by 漂泊心情.

CPlusPlus之mutable关键字

发表于 2021-12-22

在 C++ 中,mutable 是为了突破 const 的限制而设置的。被 mutable 修饰的变量,将永远处于可变的状态,即使在一个 const 函数中,甚至结构体变量或者类对象为 const,其 mutable 成员也可以被修改。

mutable的作用有两点:

  1. 保持常量对象中大部分数据成员仍然是“只读”的情况下,实现对个别数据成员的修改;
  2. 使类的const函数可以修改对象的mutable数据成员。

使用mutable的注意事项:

  1. mutable只能作用于类的非静态和非常量数据成员。
  2. 在一个类中,应尽量或者不用mutable,大量使用mutable表示程序设计存在缺陷。

参考链接

  1. c++关键字mutable作用,by 苍老流年.
  2. C++中mutable关键字存在的必要性是什么?,by zhihu.

CPlusPlus运算符重载

发表于 2021-12-22

C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。

重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。

当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。

运算符重载

您可以重定义或重载大部分 C++ 内置的运算符。这样,您就能使用自定义类型的运算符。

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

->重载

C++98 standard §13.5.6/1 “Class member access”:

An expression x->m is interpreted as (x.operator->())->m for a class object x of type T if T::operator-> exists and if the operator is selected at the best match function by the overload resolution mechanism (13.3).

函数重载

在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。

参考链接

  1. Is operator-> “chained” for pointers? [duplicate],by stackoverflow.

CPlusPlus迭代器

发表于 2021-12-22

iterator是不是pointer呢?要看container而定,由上可知,vector的iterator是pointer,list的iterator就不是pointer,而是object利用operator overloading使它表面上的操作像pointer而已,但並不是一個pointer。

参考链接

  1. iterator到底是不是pointer? (C/C++) (STL),by 真 OO无双.

CPlusPlus的using关键字用法

发表于 2021-12-21

C++ using关键字主要有三种用法:

  • 导入命名空间
1
2
3
4
5
// 导入整个命名空间到当前作用域
using namespace std;

// 只导入某个变量到当前作用域
using std::cout;
  • 指定别名

C++ 11 通过 using 指定别名,作用等同于 typedef,但相比 typedef,逻辑更直观,可读性更好。

1
2
typedef int T; // 用 T 代替 int
using T = int; // 用 T 代替 int
  • 在派生类中引用基类成员

using关键字可以让父类同名函数在子类中以重载方式使用。

参考链接

  1. c++11中的using关键字,by 蝶泳奈何桥.
  2. C++中using的三种用法 ,by 算法集市.

CPlusPlus的typename关键字

发表于 2021-12-21

“typename”是一个C++程序设计语言中的关键字。当用于泛型编程时是另一术语”class”的同义词。typename关键字主要功能有两项:

  • class关键字的同义词

这是一项C++编程语言的泛型编程(或曰“模板编程”)的功能,typename关键字用于引入一个模板参数。

  • 类型名指示符

显式地告诉编译器,T::bar是一个类型名。这就必须用typename关键字,而非模板类的静态变量。

参考链接

  1. typename,by wikipedia.
  2. 知无涯之C++ typename的起源与用法,by libfeihu.

CPlusPlus友元函数与友元类

发表于 2021-12-21

私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。

C++ 设计者认为, 如果有的程序员真的非常怕麻烦,就是想在类的成员函数外部直接访问对象的私有成员,那还是做一点妥协以满足他们的愿望为好,这也算是眼前利益和长远利益的折中。因此,C++ 就有了友元(friend)的概念。打个比方,这相当于是说:朋友是值得信任的,所以可以对他们公开一些自己的隐私。

友元分为两种:友元函数和友元类。

友元函数

在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。

友元类

一个类 A 可以将另一个类 B 声明为自己的友元,类 B 的所有成员函数就都可以访问类 A 对象的私有成员。

参考链接

  1. C++友元函数和友元类(C++ friend)详解,by c语言中文网.

Win32消息循环及窗口创建注册示例

发表于 2021-12-19

学习Windows应用程序的创建过程对理解OSG的Win32图形上下文有帮助。

Windows应用程序的创建过程

实现窗口创建的六步骤:

  1. 创建一个窗口首先要注册一个窗口类,初始化wndclass中的各个域,设置窗口过程函数。
  2. 调用RigisterClass来注册这个窗口类。
  3. 创建窗口。CreateWindow
  4. 显示窗口。ShowWindow
  5. 刷新窗口。UpdateWindow
  6. 消息循环。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Win32GUIMsg.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "Win32GUIMsg.h"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名

// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: 在此处放置代码。

// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WIN32GUIMSG, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32GUIMSG));

MSG msg;

// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}



//
// 函数: MyRegisterClass()
//
// 目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32GUIMSG));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WIN32GUIMSG);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassExW(&wcex);
}

//
// 函数: InitInstance(HINSTANCE, int)
//
// 目标: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目标: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

参考链接

  1. 消息循环,注册窗口,创建窗口【图解】,by hnfxs.
  2. Windows消息循环理解及窗体创建步骤,by LUCKYONE906.
上一页1…181920…52下一页

Jack Huang

519 日志
66 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse