博文

另类的成员函数调用(2008-06-17 11:38:00)

摘要:对于给定的一个类: class Foo{
public:
   void CALLINGCONVENTION showMe( int _d ){   //__cdecl or __stdcall is needed.
          cout << "Foo::showMe  _d = " << _d << endl;
   }
}; 通常我们会通过下面的方式进行调用该类中的成员方法: Foo foo; foo.showMe(100); 或者通过成员函数指针的形式: void (Foo::*pfn)(int) = &Foo::showMe; (foo.*pfn)(100); 我总是认为这中使用成员函数指针的调用方式(或是语法)感到很奇怪,不过它毕竟是标准的并且能够为C++编译器认可的调用方式。几乎在所有编译器都不允许将成员函数的地址直接赋给其他类型的变量(如DWORD等,即使使用reinterpret_cast也无济于事)例如:而只能将其赋给给与该成员函数类型声明(包括所使用的调用约定,返回值,函数参数)完全相同的变量。因为成员函数的声明中都有一个隐藏的this指针,该指针会通过ECX或栈的方式传递到成员函数中,为了成员函数被安全调用,编译器禁止此类型的转换也在情理当中。但有时我们为了实现特殊的目的需要将成员函数的地址直接赋给一个DWORD变量(或其他任何能够保存一个指针值的变量,通常只要是一个32位的变量即可),我们可以通过下面两种方法来实现:下面的这几种试图将一个成员函数的地址保存到一个DWORD中都将被编译器认为是语法错误:DWORD dwFooAddrPtr= 0; dwFooAddrPtr = (DWORD) &Foo::showMe; /* Error C2440 */ dwFooAddrPtr = reinterpret_cast<DWORD> (&Foo::showMe); /* Error C2440 */因为成员函数的声明中都有一个隐藏的this指针,该指针会通过E......

阅读全文(4587) | 评论:2

"Debugger detected-please close it ..."(2008-06-16 10:50:00)

摘要: 转自:http://www.directshow.cn/forum/viewthread.php?tid=3370&pid=10459&page=1&extra=page%3D2#pid10459 感谢发帖人! "Debugger detected - please close it down and restart!"问题的解决

Debugger detected  - please close it down and restart!...blahblahblah

这个问题有一些人遇到过,我也曾经遇到过,可是没有解决,直到这一次......

还是从头说起,还是GMFBridge项目,我用GMFPlay这个例子来研究GMFBridge,很快编译通过之后,我开始测试例子的功能,单独用编译出来的可执行文件可以正常执行,于是接下来很自然我认为项目已经没有问题了,开始在VS2005的IDE下执行,咦,怎么添加完文件之后就不动了,程序无响应,同时听到“邦”的一声,这是哪里出错了?还弹出了对话框?可是看不到对话框啊,这是怎么回事?折腾了半天,只是确定是在GMFBridge的Bridge.cpp 566行会出问题,就是下面这行代码:

        hr = pGraph->Render(pPin);

进一步发现是在循环第二次的时候出问题,这个时候有点挠脑袋了,为什么会在Render的时候出错呢?想跟踪也没法跟踪了。

搁了一夜,第二天想起了干脆在出错的时候dump出来分析,反正也是学习,多花点时间研究一下就是了。于是用DebugDiag(https://www.microsoft.com/downlo ... splaylang=en&tm)在出错的时候dump了一个full dump和mini dump出来,用DebugDiag分析,DebugDiag真是不错,太好用了,提示“Detected possible blocking or leaked critical section at ntdll!LdrpLoaderLock owned by threa......

阅读全文(4808) | 评论:1

“条件递进式编程”技巧两例(2008-06-03 17:02:00)

摘要:转自:http://blog.csdn.net/happydeer/archive/2004/08/06/66743.aspx#785737 什么是“条件递进式编程”?呵呵,这是我自己起的名字。所谓条件递进式编程,就是指需要一系列相关函数组合执行的情况下,后续函数执行的必要性由前面所有函数执行是否成功来决定。比如说,有一系列函数如下DoSomething1、DoSomething2、DoSomething3......DoSomethingN;DoSomething2函数执行的前提是DoSomething1函数必须执行成功,DoSomething3函数执行的前提是DoSomething1和DoSomething2都执行成功,DoSomethingN函数执行的前提是DoSomething1、DoSomething2、DoSomething3......DoSomething(N-1)都执行成功。 你会如何来写这段程序?不假思索,你可能会如下编写: BOOL DoSomething()
{
 if (DoSomething1())
 {
  if (DoSomething2())
  {
   if (DoSomething3())
   {
    // ...
    return TRUE;
   }
  }
 }
 return FALSE;
} 这种层层嵌套的结构,逻辑上并没有错,但代码的可读性就差了一点。如果系列函数的数量很多(即上述N的值很大),那么整个代码结构的宽度将变得很长,代码的可读性将进一步降低,日后修改代码的时候也很容易出错。 下面,我将给出两种我本人认为很不错的程序结构。这两种程序结构不是我自创的,但我能看到它们智慧的光芒。另外,关于以下两种程序结构,我不想给出过多解释,读者用心慢慢体会吧!
程序结构1: BOOL DoSomething()
{
 BO......

阅读全文(2567) | 评论:0

学习心得(2008-05-22 09:43:00)

摘要:此帖记录对自己学习有帮助的一些tips 1. 温故而知新     这是一句老话,回过头来想想自己走过的路,才发现这四个字价值千金。 经常总结一下,不时的回头翻翻自己的笔记,你会发现之前的想法可能有些单纯甚至错误,毕竟你现在在从一个更高的角度去看问题。在纠正和完善之中你在成长。 2.不要积攒问题     问题在刚发现的时候对它的理解总是最直接,最能接近你内心困惑的。这是个解决它的好时机。如果累积问题,慢慢的对这个问题的最初困惑会越来越不清楚,这会消磨你解决问题的热情。......

阅读全文(2499) | 评论:0

对受保护成员的一个额外访问控制(2008-05-13 11:42:00)

摘要:对于受保护的成员变量,子类对其的访问有一个额外的限制: Clause 11.5: When a friend or a member function of a derived class references a protected nonstatic member function or protected nonstatic data member of a base class, an access check applies in addition to those described earlier in clause 11.102) Except when forming a pointer to member (5.3.1), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class) (5.2.5). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class). 例子: class Base{ protected:      Base(int){}      int i; }; class Derive:public Base{ public:      Derive():Base(100){              //OK           Base b(100);        &nbs......

阅读全文(2852) | 评论:0

能在构造函数中调用虚函数吗?(2008-04-07 18:08:00)

摘要: 可以,但是你要小心,因为在构造函数里虚函数的机制并没有启用。 #include<string>
#include<iostream>
using namespace std;

class B {
public:
B(const string& ss) { cout << "B constructor\n"; f(ss); }
virtual void f(const string&) { cout << "B::f\n";}
};

class D : public B {
public:
D(const string & ss) :B(ss) { cout << "D constructor\n";}
void f(const string& ss) { cout << "D::f\n"; s = ss; }
private:
string s;
};

int main()
{
D d("Hello");
}
the program compiles and produce B constructor B::f D constructor注意:输出的是B::f,而不是D::f,因为在构建D的时候会先构建B,在B尚未完成构造的时候D是不存在的,因此如果在B中调用了还没有构建的D的成员函数(可能会修改D的变量),会导致错误。 在析构函数中同样的道理,只有本类的函数会被调用,以避免调用已经被释放的派生类的成员函数。......

阅读全文(3773) | 评论:0

C++为什么没有让delete后的指针自动清零?(2008-04-07 16:32:00)

摘要:大家都知道连续两次对同一个指针delete ,会造成严重的错误(一般的编译器会检测出这样的错误)。 于是很多人这样写delete: #define SAFE_DELETE((p)  delete (p); p = 0; 这样就可以有效地避免类似的错误,因为对零指针delete是没有害处的。可是C++为什么不支持自动对delete后的指针清零呢? 原因是,delete操作符并没有要求它的操作数必须是个左值,所以p=0这样的操作未必合法。 其次,即使C++实现了这样的机制,它也可能形同虚设,比如: class Foo; Foo *pfoo1 = new Foo(); Foo *pfoo2 = pfoo1; delete pfoo1; delete pfoo2; 最后一句一样会出同样的错。 其实想实现SAFE_DELET这样的功能有个更安全可靠的办法: template<typename T> inline void Destroy( T *&p){ delete p; p = 0;} 如此以来,便可以更安全的实现指针的释放。可这样也有一个明显的缺点, 正像它只能接受左值一样,Destroy将无法接受非左值对象: Destroy( pfoo1 ); Destroy( pfoo1+1 ); //错误(参数非左值),但delete pfoo1+1;在C++中是正确的. 所以并没有好的方法解决重复释放这样的问题,只能靠程序员的细心了。  ......

阅读全文(4143) | 评论:0

异常处理ABC(2008-04-03 11:08:00)

摘要:此文记录我对异常的一点点基本了解。欢迎大家批评指正。 http://www.microsoft.com/msj/0197/exception/exception.aspx http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx 零: c++异常用在哪里?      In C++, exceptions is used to signal errors that cannot be handled locally, such as the failure to acquire a resource in a constructor. For example: class Vector { int sz; int* elem; class Range_error { }; public: Vector(int s) : sz(s) { if (sz<0) throw Range_error(); /* ... */ } // ... }; Do not use exceptions as simply another way to return a value from a function. Most users assume - as the language definition encourages them to - that exception-handling code is error-handling code, and implementations are optimized to reflect that assumption. A key technique is resource acquisiton is initialization (sometimes abbreviated to RAII), which uses classes with destructors to impose order on resource management. For example: void fct(string s) { File_handle f(s,"r"); //......

阅读全文(2417) | 评论:0

标准C++获取文件长度的方法(2008-04-02 11:26:00)

摘要:转自http://groups.google.com/group/bruceteen/browse_thread/thread/90ef833dfbad9ab6 #include <fstream>
#include <cstdio>
using namespace std;
int main( void )
{
    fstream file( "D:\\张国荣.JPG", ios_base::binary | ios_base::in
);
    if( file.is_open() )
    {
        // ... // 这里可以进行其它操作
        fstream::pos_type cur_pos = file.tellg();
        file.seekg( 0L, ios::end );
        fstream::pos_type end_pos = file.tellg();
        file.seekg( cur_pos, ios::beg );
        streamoff flen = end_pos; // 注1
        printf( "%I64d\n", flen );
    }
    return 0;
}

// 注1: 在gcc3.4.2中 streamoff 是 int64_t.
//      而在VC++6.0中 streamoff 是 long, 所以除了标准的
//      operator fposstreamof......

阅读全文(12716) | 评论:0

Why Java Will Always Be Slower than C++(2008-03-09 22:22:00)

摘要:Why Java Will Always Be Slower than C++
by Dejan Jelovic
 
"Java is high performance. By high performance we mean adequate. By adequate we mean slow." - Mr. Bunny
Anybody that has ever used a non-trivial Java program or has programmed in Java knows that Java is slower than native programs written in C++. This is a fact of life, something that we accept when we use Java.
However, many folks would like to convince us that this is just a temporary condition. Java is not slow by design, they say. Instead, it is slow because......

阅读全文(2860) | 评论:0