??xml version="1.0" encoding="utf-8" standalone="yes"?> QFontDatabase的构造函C会调用createDatabase Q里面调用了initializeDb), initializeDb里调用了privateDb(),一个这个时候是W一ơ调用, 会生成QFontDatabasePrivate对象 QFontDatabasePrivate中的QDataStream *stream成员才是真正处理qte的字?/p> 创徏一个QT的库目,删除自动生成?h?cpp文g,d一个接口定?h文g和一个接口实现类(一?h一?cpp).代码如下: 1.接口文g源码 #ifndef PLUGININTERFACE_H #include <QString> QT_BEGIN_NAMESPACE 2.接口实现cd文g #ifndef PLUGIN_H //#include "plugin_global.h" class Plugin : public QObject, EchoInterface #endif // PLUGIN_H 3.接口实现ccpp文g #include "plugin.h" } Plugin::~Plugin() } QString Plugin::echo(const QString &message) Q_EXPORT_PLUGIN2("echoPlugin", Plugin); ~译生成dll格式的插?q里可能会遇到LNK2001错误,因ؓ插g接口定义依赖于QT的元数据,而在代码中手动添加Q_OBJECT宏后,~译器不会自动ؓ我们生成moc_XXXX.cpp文g,因此需要用命令行生成moc元数据文?cmd-->cd 源码所在命?-->moc -o moc_XXXX.cpp XXXX.h.q样可以手动创建出moc元数据文?解决LNK2001~译错误. 建立一个GUI试目,代码如下: #include "test.h" Test::Test(QWidget *parent, Qt::WFlags flags) Test::~Test() } bool Test::loadPlugin() void Test::ButtonClicked() 分析代码可见,q里Ҏ有与exe文g同目录的文g试加蝲插g,如果加蝲成功则返?代码实现非常z?在正式开发中可将已加载的插g接口存放在列表中,在需要的时候依ơ调用即? 另外如果惌取插件中cd义的元数?可以使插件接口类从QObjectl承,q用Q_CLASSINFO宏添加键值对,如Q_CLASSINFO("Author**", "Henreash**").q从ȝ序中使用插g对象元数据获取这些键值对: const QMetaObject *mo = echoInterface->metaObject(); 使用q个机制可以在定义插件类的时候向ȝ序传递一些特D信? 试发现,如果在插件接口类中定义一个静态变?那么q个静态变量在插g中的地址和在ȝ序中的地址是不相同?
@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
]]>
// [[1]] 使用typedef定义函数指针Z个类型,更喜Ƣ这U方?/font>
typedef int (*MYFUN)(int, int);
MYFUN funcs[10];
// [[2]] 使用typedef定义函数指针数组Z个类型,不是很直?/font>
typedef int (*MYFUN2[10])(int, int);
MYFUN2 funcs2;
int main(int argc, char *argv[]) {
funcs[0] = add;
qDebug() << (*funcs[0])(2, 3); // 也可以用 funcs[0](2, 3).
funcs2[0] = add;
qDebug() << (*funcs2[0])(2, 3);
return 0;
}
@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
]]>
Ҏ src/corelib/global.h template <typename T>
class QGlobalStatic
{
public:
T *pointer;
inline QGlobalStatic(T *p) : pointer(p) { }
inline ~QGlobalStatic() { pointer = 0; }
};
#define Q_GLOBAL_STATIC(TYPE, NAME) \
static TYPE *NAME() \
{ \
static TYPE this_##NAME; \
static QGlobalStatic<TYPE > global_##NAME(&this_##NAME); \
return global_##NAME.pointer; \
}
上面的展开?/span> static QFontDatabasePrivate *privateDb()
{
static QFontDatabasePrivate this_privateDb; // 注意W一ơ引用的时候会开始进行初始化, 以后不再生成
static QGLobalStatic<QFontDatabasePrivate> global_privateDb(&this_privateDb); //对上面生成的对象的指针进行包装, 同上Q只有第一ơ才会生?br />
return global_privateDb;
}
#define PLUGININTERFACE_H
class EchoInterface
{
public:
virtual ~EchoInterface() {}
virtual QString echo(const QString &message) = 0;
};
Q_DECLARE_INTERFACE(EchoInterface, "com.hollysys.plugin.EchoIntrface/1.0");
QT_END_NAMESPACE
#endif
#define PLUGIN_H
#include <QObject>
#include "plugininterface.h"
{
Q_OBJECT
Q_INTERFACES(EchoInterface)
public:
Plugin();
~Plugin();
public:
QString echo(const QString &message);
};
#include <QtGui>
Plugin::Plugin()
{
{
{
return message;
}
#include <QtGui>
#include <QMessageBox>
#include <QDir>
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QObject::connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(ButtonClicked()));
loadPlugin();
}
{
{
QDir pluginsDir(qApp->applicationDirPath());
foreach (QString filename, pluginsDir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(filename));
QObject *plugin = pluginLoader.instance();
if(plugin)
{
echoInterface = qobject_cast<EchoInterface *>(plugin);//echoInterface是成员变?br />
if(echoInterface)
return true;
}
}
}
{
QString plugin = ui.lineEdit->text();
QMessageBox::information(NULL, "", echoInterface->echo(plugin));
}
for(int i = 0; i < mo->classInfoCount(); i++)
{
qDebug() << mo->classInfo(i).name() << mo->classInfo(i).value();
}
]]>
?a title="C++" style="text-decoration: none; color: #0b0080; background-image: none; background-position: initial initial; background-repeat: initial initial; ">C++~程语言中,单例模式应用的例子如下述代码所C(q里仅仅提供一个示例,q个例子对多U程的情况ƈ不是安全的)Q?/p>
// ... class lock { public: lock(); lock(lock const & l); ~lock(); lock & operator =(lock const & l); void request(); void release(); // ... }; lock::lock() { // ... } // ... lock::~lock() { // ... } // ... void lock::request() { // ... } void lock::release() { // ... } // ... // assumes _DATA_TYPE_ has a default constructor template<typename _DATA_TYPE_> class singleton { public: static _DATA_TYPE_ * request(); static void release(); private: singleton(); singleton(singleton<_DATA_TYPE_> const & s); ~singleton(); singleton<_DATA_TYPE_> & operator =(singleton<_DATA_TYPE_> const & s); static _DATA_TYPE_ * pointer; static lock mutex; // ... }; template<typename _DATA_TYPE_> _DATA_TYPE_ * singleton<_DATA_TYPE_>::pointer = 0; template<typename _DATA_TYPE_> lock singleton<_DATA_TYPE_>::mutex; template<typename _DATA_TYPE_> _DATA_TYPE_ * singleton<_DATA_TYPE_>::request() { if(singleton<_DATA_TYPE_>::pointer == 0) { singleton<_DATA_TYPE_>::mutex.request(); if(singleton<_DATA_TYPE_>::pointer == 0) { singleton<_DATA_TYPE_>::pointer = new _DATA_TYPE_; } singleton<_DATA_TYPE_>::mutex.release(); } return singleton<_DATA_TYPE_>::pointer; } template<typename _DATA_TYPE_> void singleton<_DATA_TYPE_>::release() { if(singleton<_DATA_TYPE_>::pointer != 0) { singleton<_DATA_TYPE_>::mutex.request(); if(singleton<_DATA_TYPE_>::pointer != 0) { delete singleton<_DATA_TYPE_>::pointer; singleton<_DATA_TYPE_>::pointer = 0; } singleton<_DATA_TYPE_>::mutex.release(); } } template<typename _DATA_TYPE_> singleton<_DATA_TYPE_>::singleton() { // ... } // ... int main() { int * s; s = singleton<int>::request(); // ... singleton<int>::release(); return 0; }
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Tutors | ![]() |
Tutors source code package (tutors-src.zip 920KB) Source package + Windows executables (tutors-win32.zip 1.24MB) Source package + Mac OS X universal binaries (tutors-macosx.zip 1.2MB) Contributions from various people (Unix makefiles, etc). |
||
|
||
|
||
The lightmaterial tutorial program (shown above) demonstrates how OpenGL lighting and material properties interact and effect each other. All material & light properties are tweakable. A second command panel allows spotlight parameters & attenuation factors to be changed. |
||
|
||
|
||
The texture tutorial program (shown above) demonstrates how OpenGL texturing works. Specifically, the texture coordinates for a polygon are provided for manipulation as are the polygons coordinates themselves. The texture parameter & environment attributes are tweakable. A separate command panel allows manipulation of the texture matrix. |
||
|
![]() |
![]() |
![]() |
Q?Q显式链?/strong>
需要函数指针和WIN32 API函数LoadLibrary、GetProcAddress装蝲Q用这U蝲入方法,不需?lib文g?h头文Ӟ只需?dll文g卛_Q将.dll文g|入工程目录中)?/span>
LoadLibrary函数利用一个名UC为参敎ͼ获得DLL的实例(HINSTANCEcd是实例的句柄Q,通常调用该函数后需要查看一下函数返回是否成功,如果不成功则q回NULLQ句柄无效)Q此时调用函数FreeLibrary释放DLL获得的内存?/span>
GetProcAddress函数利用DLL的句柄和函数的名UC为参敎ͼq回相应的函数指针,同时必须使用{Q判断函数指针是否ؓNULLQ如果是则调用函数FreeLibrary释放DLL获得的内存。此后,可以使用函数指针来调用实际的函数?/span>
最后要记得使用FreeLibrary函数释放内存?/span>
注意Q应用程序如何找到DLL文gQ?/span>
使用LoadLibrary昑ּ链接Q那么在函数的参C可以指定DLL文g的完整\径;如果不指定\径,或者进行隐式链接,Windows遵循下面的搜烦序来定位DLLQ?/span>
Q?Q包含EXE文g的目?/span>
Q?Q工E目?/span>
Q?QWindowspȝ目录
Q?QWindows目录
Q?Q列在Path环境变量中的一pd目录
From: http://www.shnenglu.com/ming81/archive/2013/03/04/198215.html
.h头文件是~译时必ȝQlib是链接时需要的Qdll是运行时需要的?/span>
附加依赖的?lib不是.dllQ若生成了DLL,则肯定也生成 LIB文g。如果要完成源代码的~译和链接,有头文g和lib够了。如果也使动态连接的E序q行hQ有dll够了。在开发和调试阶段Q当然最好都有?/span>
.h .lib .dll三者的关系是:
H文g作用?声明函数接口
DLL文g作用? 函数可执行代?nbsp;
当我们在自己的程序中引用了一个H文g里的函数,~链器怎么知道该调用哪个DLL文g?q就是LIB文g的作? 告诉链接?调用的函数在哪个DLL中,函数执行代码在DLL中的什么位|?Q这也就是ؓ什么需要附加依赖项 .LIB文gQ它起到桥梁的作用。如果生成静态库文gQ则没有DLL Q只有libQ这时函数可执行代码部分也在lib文g?/span>
目前以lib后缀的库有两U,一Uؓ静态链接库(Static LibaryQ以下简U?#8220;静态库”)Q另一Uؓ动态连接库(DLLQ以下简U?#8220;动态库”)的导入库(Import LibaryQ以下简U?#8220;导入?#8221;Q。静态库是一个或者多个obj文g的打?Q所以有人干脆把从obj文g生成lib的过E称为ArchiveQ即合ƈC赗比如你链接一个静态库Q如果其中有错,它会准确的找到是哪个obj有错Q即静态lib只是壛_。动态库一般会有对应的导入库,方便E序静态蝲入动态链接库 Q否则你可能需要自己LoadLibary调入DLL文gQ然后再手工GetProcAddress获得对应函数了。有了导入库Q你只需要链接导入库后按照头文g函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一L东西。静态库本n包含了实际执行代码、符可{等Q而对于导入库而言Q其实际的执行代码位于动态库中,导入库只包含了地址W号表等Q确保程序找到对应函数的一些基本地址信息?/span>
一般的动态库E序有lib文g和dll文g。lib文g是必d~译期就q接到应用程序中的,而dll文g是运行期才会被调用的?如果有dll文gQ那么对应的lib文g一般是一些烦引信息,具体的实现在dll文g中。如果只有lib文gQ那么这个lib文g是静态编译出来的Q烦引和实现都在其中。静态编译的lib文g有好处:l用户安装时׃需要再挂动态库了。但也有~点Q就是导致应用程序比较大Q而且失去了动态库的灵zL,在版本升U时Q同时要发布新的应用E序才行。在动态库的情况下Q有两个文gQ而一个是引入库(.LIBQ文Ӟ一个是DLL文gQ引入库文g包含被DLL导出的函数的名称和位|,DLL包含实际的函数和数据Q应用程序用LIB文g链接到所需要用的DLL文gQ库中的函数和数据ƈ不复制到可执行文件中Q因此在应用E序的可执行文g中,存放的不是被调用的函C码,而是DLL中所要调用的函数的内存地址Q这样当一个或多个应用E序q行是再把程序代码和被调用的函数代码链接hQ从而节省了内存资源。从上面的说明可以看出,DLL?LIB文g必须随应用程序一起发行,否则应用E序会产生错误?/span>
静态库和共享库都是一个obj文g的集?Q但静态链接后Q执行程序中存在自己所需obj的一份拷贝,而动态链接后Q执行程序仅仅是包含对共享库的一个引用。共享库相当于一个由多个obj文gl合而成的obj文gQ在链接后其所有代码被加蝲Q不需要的q是不需要的?/span>
g可以得出一个结论:
静态链接后的程序比动态链接的所用存储空间大Q因为执行程序中包含了库中代码拷贝;
而动态链接的E序比静态链接的所用的q行I间大,因ؓ它将不需要的代码也加载到q行I间?/span>
针对上面的知? 个问题:
1Q?DLL?LIB文g必须随应用程序一起发行,否则应用E序会产生错误?nbsp;
我的{案Qlib应该不需要吧?br />
2Q如果是某个E序中调用了一个动态库Q通过header文gQlib+dll来调用)Q则对动态库的某个函数的内容修改了,但接口不改,则调用此动态库的程序需重新~译q接吗?如果是通过loadlibary动态加载,需要重新编译连接吗Q?br />
目前有很多不同类型的版本控制pȝQVersion Control SystemQ?VCSQ。一些VCSQ比?a style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #003366; text-decoration: none; ">Subversion?a style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #003366; text-decoration: none; ">CVSQ以中央仓库QrepositoryQؓ中心q行架构。此外,q有分布式的VCSQDistributed VCSQDVCSQ, Git ?nbsp;Mercurial 是两个新q出现的DVCS。然而,在上qCU类型的环境中,通常会有一?#8220;指定?#8221;中央仓库。对应地Q比如一个Subversion服务器或者一?a style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #003366; text-decoration: none; ">GitHub仓库。下面会Zq个场景q行囄说明。那么让我们开始吧?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
在开发者拷贝到本机之前Q服务器需要创Z个仓库。创建初始仓库会׃产品不同而有所差别。从现在P你所要知道的是Q在服务器上有一个初始空间。我把这个版本称作版?#8220;A”?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
现在Q每个开发者(开发?和开发?Q都会拷贝版?#8220;A”C们本地电脑。再一ơ地Q从服务器拷贝的q程会由于品不同采用的技术会有所差别?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
每个开发者会在他们的本地拯上进行开发。他们的本地拯Z版本“A”。然而,׃他们应该不会做同L开发,因而他们的版本会有所差别。因此,会有2个以上的版本会同时被创徏Q比如版?#8220;B”和版?#8220;C”?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
开发?首先完成了她的工作ƈ提交到服务器。服务器上的当前版本被更新成版本“B”?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
开发?现在完成了他的工作ƈ试图提交到服务器。然而,q是服务器告知他Z开发的版本已经发生改变?strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">q也是ؓ什么采取版本控制的首要原因之一?/strong>q个Ҏ是对网l共享代码然后由开发者手动更新的一个跨式发展Q这保了之前的~辑没有被新的修改覆盖?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
开发?必须首先获得所有版?#8220;B”的变化,q合q到他的修改中,然后才可以提交到服务器。这个过E听h有些复杂。然而,大多数现代的版本控制pȝ十分高Q能够自动在开发者的本地拯上完成合q。有几种情况会生冲H(例如Q开发?和开发?同时修改了同一个文件的同一行)。这是一些VCS产品比其他更高的地斏V不论如何完成合qӞ现在开发?在他们的本地pȝ上同时合了版本B和版本C?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
现在开发?可以提交他的版本到服务器?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
q是一个版本控制的基础。通过注意观察图中服务器的q线可以发现版本控制的原理。服务器记录了所有先前的版本包括发生的变化,什么时候发生以及由谁进行修攏V当需要进行代码回溯或者引入其他bugӞq个记录能够解除困境?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />我希望本文能够ؓ版本控制pȝ提供一个基的介l。如果你有Q何疑问,请就你问题发表评论?br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />
英文原文Q?a style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #003366; text-decoration: none; ">greenmoonsoftware ~译Q?a style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #003366; text-decoration: none; ">伯乐在线 – 唐尤?/a>
#include <stdlib.h> void qsort( void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) ); |
#include <stdlib.h> void *bsearch( const void *key, const void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) ); |
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cmath>
using namespace std;
void queen(int** array, int row, FILE* fp);
bool isAvailable(int** array, int y, int x);
bool isResult(int** array);
int main(int arg, char** argv) {
int** array;
// 分配I间
array = new int*[8];
for (int i = 0; i < 8; i++) {
array[i] = new int[8];
}
// 初始化皇后状?/font>
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
array[i][j] = 0;
}
}
FILE* fp = fopen("data.txt", "w");
queen(array, 0, fp);
fclose(fp);
// 释放I间
for (int i = 0; i < 8; i++) {
delete[] array[i];
}
delete array;
array = NULL;
return 0;
}
void queen(int** array, int row, FILE* fp) {
static int size = 1;
if (row > 7) {
return;
}
for (int j = 0; j < 8; j++) {
// 如果合法
if (isAvailable(array, row, j)) {
array[row][j] = 1;
// 当前位置合法Q赋值后Q进入下一?br style="line-height: 15px; "> queen(array, row + 1, fp);
// 如果退回来后是l果Q则打印出来
if (isResult(array)) {
// 把结果写入文?br style="line-height: 15px; "> fputc('\n', fp);
fputs("***********************************", fp);
fprintf(fp, " %d ", size++);
fputs("***********************************", fp);
fputc('\n', fp);
for (int m = 0; m < 8; m++) {
for (int n = 0; n < 8; n++) {
if (array[m][n] == 1) {
fputc('#', fp);
fputc(' ', fp);
fputc(' ', fp);
} else {
fputc('O', fp);
fputc(' ', fp);
fputc(' ', fp);
}
}
fputc('\n', fp);
}
}
array[row][j] = 0;
}
}
}
bool isAvailable(int** array, int row, int column) { // Wrow行,column?br style="line-height: 15px; "> int i, j;
// 查row?/font>
for (i = 0; i < 8; i++) {
if (array[row][i] != 0) {
return false;
}
}
// columnx?/font>
for (j = 0; j < 8; j++) {
if (array[j][column] != 0) {
return false;
}
}
// 查对角向左上
i = row;
j = column;
while (i >= 0 && j >= 0) {
if (array[i][j] != 0) {
return false;
}
i--;
j--;
}
// 查对角向右上
i = row;
j = column;
while (i >= 0 && j < 8) {
if (array[i][j] != 0) {
return false;
}
i--;
j++;
}
// 查对角向左下
i = row;
j = column;
while (i < 8 && j >= 0) {
if (array[i][j] != 0) {
return false;
}
i++;
j--;
}
// 查对角向右下
i = row;
j = column;
while (i < 8 && j < 8) {
if (array[i][j] != 0) {
return false;
}
i++;
j++;
}
return true;
}
bool isResult(int** array) {
int size = 0; // 皇后个数
// l计皇后个数
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (array[i][j] != 0) {
size++;
}
}
}
// 没有Q个皇后Q说明不是结?/font>
// ?个皇?因ؓ每个皇后的放|都是在合法位置, 所以只需要简单的计算皇后个数q道是不是l果.
if (size != 8) {
return false;
}
return true;
}
#include <stdio.h>
#include <math.h>
int main() {
double y;
int x, f, i;
/* 输出正玄, 单调区间 x: [-pi/2, pi/2], y: [-1, 1] */
/* 要分成两个部分来计算输出 */
for (y = 1; y > 0; y -= 0.1) {
x = asin(y) * 10;
for (i = 1; i < x; ++i) printf(" ");
printf("*");
for (; i < 32 - x; ++i) printf(" ");
printf("*\n");
}
for (y = 0; y >= -1; y -= 0.1) {
x = asin(y) * 10; /* x是负?*/
for (i = 1; i < 34 - x; ++i) printf(" ");
printf("*");
for (; i < 66 + x; ++i) printf(" ");
printf("*\n");
}
printf("\n\n");
/* 输出余玄, 单调区间 x: [0, pi], y: [1, -1] */
for (y = 1; y >= -1; y -= 0.1) {
x = (int)(acos(y) * 10);
for (i = 0; i <= 64; ++i) {
if (i == x || i == 64 - x) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
}
I am in a different position with respect to this fix. I had installed cmake 2.8.2_3 before the Apple Java update. After the Apple Java update, the cmake upgrade from 2.8.2_3 to 2.8.2_4 failed saying that I needed to install Java from Apple, which was already installed. As far as I can tell, the Apple update to Java 1.6.0_22 did not properly update the header path. In the updated version the header path leads to a dead end. I was able to fix this by doing the following.
1) Create directory
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Headers
2) Copy entire contents of directory
/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers
to directory
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Headers
After this fix the upgrade to cmake 2.8.2_4 worked. However, if the macports cmake could be made to look for the Java headers in /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers this would resolve an existing problem.
From: https://trac.macports.org/ticket/26934
5. 最l大戏来了,安装OpenCV: http://sunny.in.th/2010/04/27/installing-opencv-21-on-snow-leopard.html
Installing OpenCV 2.1 on Snow Leopard has become quite easy at least easier than 2.0. Version 2.1 can now be compiled as 64-bit library.
Before version 2.1 OpenCV used Carbon which is the old GUI interface for Mac OS. Carbon supports only 32-bit and has been deprecated by Apple. The new GUI interface for Mac OS is Cocoa. With Snow Leopard being a 64-bit kernel it would be nice if we could compile OpenCV as a 64-bit library and not not 32-bit just because of Carbon. Thanks to the OpenCV team they have added Cocoa support in version 2.1.
To install OpenCV check out the code from the svn repository and compile it.
$ svn co https://code.ros.org/svn/opencv/trunk/opencv
$ cd opencv
$ mkdir build
$ cd build
$ cmake ..
Configure the make by
$ ccmake .
If you want you can build the samples as well.
Press c
to configure, followed by g
to generate. Next build and install OpenCV by
$ make -j8
$ sudo make install
That’s it!!! Simple right.
If you want to use Python with OpenCV there’s a little more that needs to be done. By default OpenCV copies the shared object file required by the Python interface to /usr/local/lib/python2.6/site-packages/cv.so
which is not under Python path. Add the following line to your .bashrc
or .bash_profile
PYTHONPATH=/usr/local/lib/python2.6/site-packages/cv.so:$PYTHONPATH
Trying running some C
samples which are in /usr/local/share/opencv/samples/c/
. The Python samples at/usr/local/share/opencv/samples/python/
doesn’t work since they are based on the old SWIG-Python interface. Try running the sample Python code which is in the opencv
directory that was checked out from subversion. It’s insidesamples/python
.
short a=2000; int b; b=a; |
Here, the value of a has been promoted from short to int and we have not had to specify any type-casting operator. This is known as a standard conversion. Standard conversions affect fundamental data types, and allow conversions such as the conversions between numerical types (short to int, int to float, double to int...), to or from bool, and some pointer conversions. Some of these conversions may imply a loss of precision, which the compiler can signal with a warning. This can be avoided with an explicit conversion.
Implicit conversions also include constructor or operator conversions, which affect classes that include specific constructors or operator functions to perform conversions. For example:
class A {}; class B { public: B (A a) {} }; A a; B b=a; |
Here, a implicit conversion happened between objects of class A and class B, because B has a constructor that takes an object of class A as parameter. Therefore implicit conversions from A to B are allowed.
short a=2000; int b; b = (int) a; // c-like cast notation b = int (a); // functional notation |
The functionality of these explicit conversion operators is enough for most needs with fundamental data types. However, these operators can be applied indiscriminately on classes and pointers to classes, which can lead to code that while being syntactically correct can cause runtime errors. For example, the following code is syntactically correct:
// class type-casting #include <iostream> using namespace std; class CDummy { float i,j; }; class CAddition { int x,y; public: CAddition (int a, int b) { x=a; y=b; } int result() { return x+y;} }; int main () { CDummy d; CAddition * padd; padd = (CAddition*) &d; cout << padd->result(); return 0; } |
The program declares a pointer to CAddition, but then it assigns to it a reference to an object of another incompatible type using explicit type-casting:
padd = (CAddition*) &d; |
Traditional explicit type-casting allows to convert any pointer into any other pointer type, independently of the types they point to. The subsequent call to member result will produce either a run-time error or a unexpected result.
In order to control these types of conversions between classes, we have four specific casting operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new_type) expression
new_type (expression)
but each one with its own special characteristics:
dynamic_cast can be used only with pointers and references to objects. Its purpose is to ensure that the result of the type conversion is a valid complete object of the requested class.
Therefore, dynamic_cast is always successful when we cast a class to one of its base classes:
class CBase { }; class CDerived: public CBase { }; CBase b; CBase* pb; CDerived d; CDerived* pd; pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived |
The second conversion in this piece of code would produce a compilation error since base-to-derived conversions are not allowed with dynamic_cast unless the base class is polymorphic.
When a class is polymorphic, dynamic_cast performs a special checking during runtime to ensure that the expression yields a valid complete object of the requested class:
// dynamic_cast #include <iostream> #include <exception> using namespace std; class CBase { virtual void dummy() {} }; class CDerived: public CBase { int a; }; int main () { try { CBase * pba = new CDerived; CBase * pbb = new CBase; CDerived * pd; pd = dynamic_cast<CDerived*>(pba); if (pd==0) cout << "Null pointer on first type-cast" << endl; pd = dynamic_cast<CDerived*>(pbb); if (pd==0) cout << "Null pointer on second type-cast" << endl; } catch (exception& e) {cout << "Exception: " << e.what();} return 0; } | Null pointer on second type-cast |
Compatibility note: dynamic_cast requires the Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This must be enabled for runtime type checking using dynamic_cast to work properly. |
The code tries to perform two dynamic casts from pointer objects of type CBase* (pba and pbb) to a pointer object of type CDerived*, but only the first one is successful. Notice their respective initializations:
CBase * pba = new CDerived; CBase * pbb = new CBase; |
Even though both are pointers of type CBase*, pba points to an object of type CDerived, while pbb points to an object of type CBase. Thus, when their respective type-castings are performed using dynamic_cast, pba is pointing to a full object of class CDerived, whereas pbb is pointing to an object of class CBase, which is an incomplete object of class CDerived.
When dynamic_cast cannot cast a pointer because it is not a complete object of the required class -as in the second conversion in the previous example- it returns a null pointer to indicate the failure. If dynamic_cast is used to convert to a reference type and the conversion is not possible, an exception of type bad_cast is thrown instead.
dynamic_cast can also cast null pointers even between pointers to unrelated classes, and can also cast pointers of any type to void pointers (void*).
class CBase {}; class CDerived: public CBase {}; CBase * a = new CBase; CDerived * b = static_cast<CDerived*>(a); |
This would be valid, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.
static_cast can also be used to perform any other non-pointer conversion that could also be performed implicitly, like for example standard conversion between fundamental types:
double d=3.14159265; int i = static_cast<int>(d); |
Or any conversion between classes with explicit constructors or operator functions as described in "implicit conversions" above.
It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it, is granted to be able to be cast back to a valid pointer.
The conversions that can be performed by reinterpret_cast but not by static_cast have no specific uses in C++ are low-level operations, whose interpretation results in code which is generally system-specific, and thus non-portable. For example:
class A {}; class B {}; A * a = new A; B * b = reinterpret_cast<B*>(a); |
This is valid C++ code, although it does not make much sense, since now we have a pointer that points to an object of an incompatible class, and thus dereferencing it is unsafe.
// const_cast #include <iostream> using namespace std; void print (char * str) { cout << str << endl; } int main () { const char * c = "sample text"; print ( const_cast<char *> (c) ); return 0; } | sample text |
typeid (expression)
This operator returns a reference to a constant object of type type_info that is defined in the standard header file <typeinfo>. This returned value can be compared with another one using operators == and != or can serve to obtain a null-terminated character sequence representing the data type or class name by using its name() member.
// typeid #include <iostream> #include <typeinfo> using namespace std; int main () { int * a,b; a=0; b=0; if (typeid(a) != typeid(b)) { cout << "a and b are of different types:\n"; cout << "a is: " << typeid(a).name() << '\n'; cout << "b is: " << typeid(b).name() << '\n'; } return 0; } | a and b are of different types: a is: int * b is: int |
When typeid is applied to classes typeid uses the RTTI to keep track of the type of dynamic objects. When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:
// typeid, polymorphic class #include <iostream> #include <typeinfo> #include <exception> using namespace std; class CBase { virtual void f(){} }; class CDerived : public CBase {}; int main () { try { CBase* a = new CBase; CBase* b = new CDerived; cout << "a is: " << typeid(a).name() << '\n'; cout << "b is: " << typeid(b).name() << '\n'; cout << "*a is: " << typeid(*a).name() << '\n'; cout << "*b is: " << typeid(*b).name() << '\n'; } catch (exception& e) { cout << "Exception: " << e.what() << endl; } return 0; } | a is: class CBase * b is: class CBase * *a is: class CBase *b is: class CDerived |
Notice how the type that typeid considers for pointers is the pointer type itself (both a and b are of type class CBase *). However, when typeid is applied to objects (like *a and *b) typeid yields their dynamic type (i.e. the type of their most derived complete object: 真实的类型,即子类对象使用的是父类的指针,但返回的子类的信?.
If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.