C++、Java、Delphi类继承的对比

总体来说

  • c++: 完全的控制,极大的灵活性,灵活带来的复杂
  • java:比c++"保守",虚拟机风格的体系结构
  • delphi:很保守

inclusion/using clause

#include <iostream>
using namespace std;
import java.io.*;
uses windows,system,sysutils;

inheritance
class Child:[public | protected | private] Fahter,public Mother{
            ...
}

C++是这三种语言中继承最为复杂的.
分为 public,protected,private继承,同时支持真正的多继承

public继承(又称类型继承)和java的继承一样,保持父类的访问控制

protected继承将父类public成员改变为protected的

private继承(又称实现继承)不直接支持父类的公有接口,而提供自己的公有接口

所以private继承中,子类将父类中原先的protected成员和public成员都置为private的
所以原则上private继承中的子类应该是继承树中的叶节点,它只有private和public成员而
没有protected成员.它不应该再被继承,类似于Java中的final class

class Child extends Father implements IInterface{
            ...
}
TChild = class(TFather,IInterfacedObject)
            ...
end;

java 和 delphi 的继承相似,都是单继承同时可以实现多个接口

Access Control/Organization

class Foo{
   private:
    int i;
             int j;
             void f();
   protected: 
             int k;
   public: 
             int o;
}

class Foo /* extends Object */ {
  private
             int i;
             int j;
             void f(){...};
   protected
             int k;
   public
             int o;
}
TFoo = class(TObject)
   private 
             i:Integer;
             j:Integer;
   protected
             k:Integer;
   public
             o:Integer;
   publicshed
   property
             Tag:Integer read i write i;
end;

如果不给出访问控制,
c++默认是private
java默认是包内可见的
delphi默认是public的(单元内可见?)

c++的访问控制和代码管理最为丰富:
可以通过#include包含c/cpp头文件,提供向c的兼容
同时可以使用名字空间防止名字冲突,并且像c一样将代码分为头文件和实现文件
同时丰富性也带来了复杂性.使得c++的文件组织没有java和delphi清晰

java提供了松散的代码组织方式–包(package),而delphi提供了单元的代码组织方法
这两种组织方法相似,都是给了我们一个存放一组相关类的地方.而这个地方,在java中
是一个文件系统上的文件夹,在delphi中是一个单元文件
相比之下,我还是喜欢Delphi的组织方法:当类很多的时候java包中的文件变得既多又不好管理

虚函数 vs 动态函数

C++中有虚函数。而Delphi中既有虚函数还有动态函数。二者在语义上是等价的。

Virtual and dynamic methods are semantically equivalent. They differ only in the implementation of method-call dispatching at runtime.

区别在于虚函数优化了速度,而动态函数优化了代码大小

Virtual methods optimize for speed, while dynamic methods optimize for code size.

In general, virtual methods are the most efficient way to implement polymorphic behavior.

总体上来讲,虚函数是实现多态行为的最有效的方法

Dynamic methods are useful when a base class declares many overridable
methods which are inherited by many descendant classes in an application, but only
occasionally overridden.

当基类声明了很多可重写但是很少重写的方法时使用动态函数,
这样可一减小代码大小。在设计Framework时常使用这个技术

MFC学习笔记#1

作为Windows的Framework需要解决的一个问题就是
消息映射 Message Mapping

Delphi中由于有编译器的支持,可以直接在用户编写的类中处理需要处理的消息:

procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;

在MFC中就比较复杂了. afx使用宏来实现Windows消息到处理函数的映射而没有使用会带
而外的开销:由于C++中实现虚函数需要一个分发表vtable,而无论子类是否重写父类的虚函数,
都需要4个字节的开销.在CWnd类中至少要处理100个以上的消息.这样设计会带来很大的问题.

afx用一组宏将用于消息映射的数据保存在类中.大概情况是:记录该类可以处理的Windows消息,
当消息来到时,对比自己可以处理的消息列表,如果可以处理,就交给列表中记录的函数来处理.
而这个函数就是我们自己些的.比如 OnLButtonDown等

afx.h 中声明了mfc中最基础的类

struct CRuntimeClass;                  // object type information

class CObject;                                // the root of all objects classes

class CException;                         // the root of all exceptions
          class CArchiveException;              // archive exception
          class CFileException;                 // file exception
          class CSimpleException;
           class CMemoryException;               // out-of-memory exception
           class CNotSupportedException; // feature not supported exception

class CFile;                              // raw binary file
          class CStdioFile;                     // buffered stdio text/binary file
          class CMemFile;                       // memory based file

// Non CObject classes
class CString;                                // growable string type
class CTimeSpan;                              // time/date difference
class CTime;                                  // absolute time/date
struct CFileStatus;                           // file status information
struct CMemoryState;                          // diagnostic memory support

class CArchive;                               // object persistence tool
class CDumpContext;                           // object diagnostic dumping

先看一下CRuntimeClass

struct CRuntimeClass
{
// Attributes
LPCSTR m_lpszClassName;//保存类名
int m_nObjectSize;//类对象大小
UINT m_wSchema; // schema number of the loaded class//是否可序列化
CObject* (PASCAL* m_pfnCreateObject)(); // 指向类的构造函数的指针

           //指向父类CRuntimeClass的指针
#ifdef _AFXDLL
CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
CRuntimeClass* m_pBaseClass;
#endif

// Operations
CObject* CreateObject(); //动态创建
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; //类型鉴别

// Implementation
void Store(CArchive& ar) const; //序列化
static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum) ;//"反序列化"

// CRuntimeClass objects linked together in simple list
CRuntimeClass* m_pNextClass;               // linked list of registered classes //注册类列表
};

CRuntimeClass 是MFC中很重要的一个类,动态创建实例是最常用的功能之一

// Helper macros for declaring CRuntimeClass compatible classes

#ifdef _AFXDLL
#define DECLARE_DYNAMIC(class_name) 
protected: 
static CRuntimeClass* PASCAL _GetBaseClass(); 
public: 
static const AFX_DATA CRuntimeClass class##class_name; 
virtual CRuntimeClass* GetRuntimeClass() const; 

#define _DECLARE_DYNAMIC(class_name) 
protected: 
static CRuntimeClass* PASCAL _GetBaseClass(); 
public: 
static AFX_DATA CRuntimeClass class##class_name; 
virtual CRuntimeClass* GetRuntimeClass() const; 

#else
#define DECLARE_DYNAMIC(class_name) 
public: 
static const AFX_DATA CRuntimeClass class##class_name; 
virtual CRuntimeClass* GetRuntimeClass() const; 

#define _DECLARE_DYNAMIC(class_name) 
public: 
static AFX_DATA CRuntimeClass class##class_name; 
virtual CRuntimeClass* GetRuntimeClass() const; 

#endif

// not serializable, but dynamically constructable
#define DECLARE_DYNCREATE(class_name) 
DECLARE_DYNAMIC(class_name) 
static CObject* PASCAL CreateObject();

#define _DECLARE_DYNCREATE(class_name) 
_DECLARE_DYNAMIC(class_name) 
static CObject* PASCAL CreateObject();

#define DECLARE_SERIAL(class_name) 
_DECLARE_DYNCREATE(class_name) 
AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

CObject
基本服务:

BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const; //类型鉴别

// Overridables
virtual void Serialize(CArchive& ar); //序列化

// Diagnostic Support //诊断支持
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;

//动态创建,利用CRuntimeClass里的m_pfnCreateObject
CObject* CRuntimeClass::CreateObject()

CWnd 在afxwin.h中定义,在wincore.cpp中实现
CWnd封装的功能

// Window tree access
// Message Functions
// Message processing for modeless dialog-like windows
// Window Text Functions
// CMenu Functions - non-Child windows only
// Window Size and Position Functions
// Coordinate Mapping Functions
// Update/Painting Functions
// Timer Functions
// ToolTip Functions
// Window State Functions
// Dialog-Box Item Functions
// Scrolling Functions
// Window Access Functions
// Alert Functions
// Clipboard Functions
// Caret Functions
// Shell Interaction Functions
// Icon Functions
// Context Help Functions
// Dialog Data support
// Help Command Handlers
// Layout and other functions
// OLE control wrapper functions

/* 消息处理函数 */
// Window-Management message handler member functions
// Nonclient-Area message handler member functions
// System message handler member functions
// Input message handler member functions
// Initialization message handler member functions
// Clipboard message handler member functions
// Control message handler member functions
// MDI message handler member functions
// Menu loop notification messages

Windows 控件的实现文件在 winctrl1.cpp~winctrl7.cpp

初识lambda

lamda{||block} ->aProc

Kernel::Proc的同义语
lamda{block} 等价于 proc{block}

例子:

print "(t)imes or (p)lus: "
times = gets
print "number: "
number = Integer(gets)


if times =~ /^t/
calc = lambda {|n| n*number }
else
calc = lambda {|n| n+number }
end

puts((1..10).collect(&calc).join(", "))

15:39 2008-3-17 补充

Python中的lambda:

def make_repeater(n):
     return lambda s: s*n

twice = make_repeater(2)
print twice("word")
c:> wordword

Python中的lambda只能使用expression,不能使用statement

Scroll to top