所有網頁 圖片 影片 地圖 新聞 網誌搜尋 Gmail 更多 »
最近造訪的群組 | 說明 | 登入
Google 網上論壇首頁
[c++]问题c++的封装是语法层次而不是binary层的, 如何理解?
目前本群組有太多主題設為優先顯示。要優先顯示這個主題,請將其他主題的這個選項取消。
在處理您的要求時發生錯誤。請再試一次。
標幟
  1 - 25 個留言 (共 35 個) - 全部摺疊  -  將全文翻譯為 已翻譯 (查看所有原文)   較新 >
您要留言的群組是 Usenet 群組。在此群組留言,網際網路上的任何使用者將可以看到您的電郵地址。
您的回覆郵件尚未寄出。
您已成功留言
 
寄件人:
收件人:
副本:
後續追蹤對象:
新增副本 | 新增後續追蹤對象 | 編輯主旨
主旨:
驗證:
為了確認,請輸入您在以下圖片中看到的字元,或輸入您按下存取圖示時所聽到的號碼。 注意聽並輸入您聽到的號碼
 
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午4時58分
寄件人: sagasw <sag...@gmail.com>
日期: Tue, 30 Jun 2009 16:58:23 +0800
當地時間: 2009年6月30日(星期二) 下午4時58分
主旨: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

今天看一个内部培训的ppt,不是很理解,望各位达人赐教。

C++ supports encapsulation only at a syntactic level, not at a binary level.

// person.h
class CPerson
{
public:
    CPerson();
    virtual ~CPerson();
    ...
private:
    CString m_Name;
    int     m_Age;

};

// client.cpp
#include "Person.h"

void Foo()
{
    CPerson p1;

}

Even though Foo() will not be allowed to access the private members of
CPerson, it must know how much memory to allocate for the CPerson object p1.

This violates encapsulation, because CPerson cannot change its
implementation details without affecting Foo() (and other clients).

上面问题简单说就是client.cpp里面不知道该如何分配CPerson大小。ppt里给出一个解决方法是person.h中提供了一个静态方法来new一 个CPerson对象,而微软的COM技术也是做了类似的包装范式。

CPerson* CreatePerson()
{
    return new CPerson;

}

*我的问题是对于其他操作系统或者windows上非微软系的,使用的是什么技术来解决这个问题的?*

    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
討論主旨已變更為 "[TL][c++]问题c++的封装是语法层次而不是binar y层的,如何理解?" 由 SpitFire 著作
SpitFire  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時05分
寄件人: SpitFire <spitfi...@gmail.com>
日期: Tue, 30 Jun 2009 17:05:16 +0800
當地時間: 2009年6月30日(星期二) 下午5時05分
主旨: Re: [TL] [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

没看出来为什么不知道CPerson的大小,是在某个特定的场景?

2009/6/30 sagasw <sag...@gmail.com>

--
SpitFire

    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
jinhu wang  
檢視個人資料   翻譯為 已翻譯 (查看原文)
(1 位使用者)  更多選項 6月30日, 下午5時07分
寄件人: jinhu wang <wangjinhu...@gmail.com>
日期: Tue, 30 Jun 2009 17:07:15 +0800
當地時間: 2009年6月30日(星期二) 下午5時07分
主旨: Re: [TL] [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?
意思就是说在语法上你没法访问私有变量,但是并不是真的没有其他办法访问。
如下定义
class C_c
{
        int i;//此类中的i是私有的不能被访问
};

struct C_s
{
        int i;//结构体中的i是共有的
}

union
{
        C_c cc;
        C_s cs;
        }c_u;
当执行c_u.cs = 100;
间接地的操作了class C_c的私有变量。
2009/6/30 sagasw <sag...@gmail.com>:


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
討論主旨已變更為 "[c++]问题c++的封装是语法层次而不是binary层的, 如何理解?" 由 sagasw 著作
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時08分
寄件人: sagasw <sag...@gmail.com>
日期: Tue, 30 Jun 2009 17:08:11 +0800
當地時間: 2009年6月30日(星期二) 下午5時08分
主旨: Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

http://yosefk.com/c++fqa/defective.html
自己找了一个资料,里面说的还算详细,但是没有解决方法。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時11分
寄件人: sagasw <sag...@gmail.com>
日期: Tue, 30 Jun 2009 17:11:42 +0800
當地時間: 2009年6月30日(星期二) 下午5時11分
主旨: Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

这个ppt里面其实也算说的比较明白,需要想想才能想通。
如果不使用另外一个接口函数来生成对象,每次CPerson的成员变动都需要client重新编译。这也是那个c++fqa里面提到的“没有编译期间封装”。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
討論主旨已變更為 "[TL][c++]问题c++的封装是语法层次而不是binar y层的,如何理解?" 由 up duan 著作
up duan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時18分
寄件人: up duan <fixo...@gmail.com>
日期: Tue, 30 Jun 2009 17:18:02 +0800
當地時間: 2009年6月30日(星期二) 下午5時18分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

C++缺乏ABI。唯一跟【至少是现在】BinarySpec相关的构造是sizeof运算符,不过受到一定的限制。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
SpitFire  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時18分
寄件人: SpitFire <spitfi...@gmail.com>
日期: Tue, 30 Jun 2009 17:18:36 +0800
當地時間: 2009年6月30日(星期二) 下午5時18分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

 编译防火墙技术 pimpl

2009/6/30 sagasw <sag...@gmail.com>

--
SpitFire

    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
qiaojie  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時20分
寄件人: qiaojie <qiao...@gmail.com>
日期: Tue, 30 Jun 2009 17:20:49 +0800
當地時間: 2009年6月30日(星期二) 下午5時20分
主旨: Re: [TL] [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

用C接口来导出。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時23分
寄件人: sagasw <sag...@gmail.com>
日期: Tue, 30 Jun 2009 17:23:27 +0800
當地時間: 2009年6月30日(星期二) 下午5時23分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

c++相互之间如果还需要c来作为导出,真是说不过去啊。

2009/6/30 qiaojie <qiao...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
qiaojie  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時27分
寄件人: qiaojie <qiao...@gmail.com>
日期: Tue, 30 Jun 2009 17:27:29 +0800
當地時間: 2009年6月30日(星期二) 下午5時27分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

这也是C++为人所诟病的一大缺点。所以你看到底层系统软件绝少用C++写,几乎全是C的天下,就算用C++写的,对外也一定是C风格的API接口。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Fei Yan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午6時31分
寄件人: Fei Yan <skyscribe...@gmail.com>
日期: Tue, 30 Jun 2009 18:31:41 +0800
當地時間: 2009年6月30日(星期二) 下午6時31分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

楼主说的应该不是ABI的问题,而是封装的隐式依赖:
             外部用户虽然不关心对象的大小,当时每次对象的大小发生变化的时候,外部代码必须重新编译;

即使换做C接口,那么某些隐含的成员类型变换的时候,外部用到这个结构体的函数还是要重新编译。

针对楼主所说的这个问题,解决的方法应该是Pimpl编译期防火墙技术,通过引入不透明的一个指针来解决该问题,因为所有指针类型的大小都是确定的,因此即使是 类的非公有数据发生变化,那么对象的大小对于外部用户来说是不变的。

class CPersion
{
public:
     CPerson();
     virtual ~CPerson();

     void PublicMethods();
     .........

private:
     class PersonImpl;
     PersonImpl*    m_impl;

};

2009/6/30 up duan <fixo...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
up duan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午6時35分
寄件人: up duan <fixo...@gmail.com>
日期: Tue, 30 Jun 2009 18:35:56 +0800
當地時間: 2009年6月30日(星期二) 下午6時35分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

这不是ABI的一个重要部分么?

2009/6/30 Fei Yan <skyscribe...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Fei Yan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午7時20分
寄件人: Fei Yan <skyscribe...@gmail.com>
日期: Tue, 30 Jun 2009 19:20:17 +0800
當地時間: 2009年6月30日(星期二) 下午7時20分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

也可以算作是ABI,但是问题本身和c++在ABI上边的缺陷没有必然联系吧。

一般c++ 特有的ABI缺陷引发的问题指代的应该是name mangling, vtable, virtual base, virtual
inheritance, multiple inheritance, object alignment, data members' relative
order.这些方面的问题一般是用户不应该关心的,但由于c++语言本身不能很好的提供可移植的方案,导致编译器实现细节的耦合。

对于楼主这个问题,我认为不应该把其归结为ABI的问题,而是如何隐藏外部用户不关心的实现细节的问题;虽然推广说来,一切和实现细节相关的东西都能引申到AB I上来。即使是个ABI问题,那么也是c、c++都有的问题,
那么往底层说开来,也可以说是OS的ABI问题,这一个层面问题也是有不少的,像byte order, alignment, bit field等。

作为一类和底层直接打交道的语言,c/c++都不可避免类似的ABI不兼容的麻烦。Java、Python都没有类似的问题,因为它们自己做了一个中间层,把底 层操作都隔离起来了,用户看不到真正的字节;而Pimpl起到的作用是类似的,是语言之上的一个模拟,可以解决楼主关心的问题的主要矛盾,也就是:
Foo() must know how much memory to allocate for the CPerson object p1.

经过pimpl之后,Foo()并不需要知道分配多少内存给p1, 因为对于Foo而言,CPerson对象的大小可以认为是不变的。

2009/6/30 up duan <fixo...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
qiaojie  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午8時14分
寄件人: qiaojie <qiao...@gmail.com>
日期: Tue, 30 Jun 2009 20:14:25 +0800
當地時間: 2009年6月30日(星期二) 下午8時14分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

确实,这个问题跟ABI没关系

2009/6/30 Fei Yan <skyscribe...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Dai Shuo  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 6月30日, 下午5時13分
寄件人: Dai Shuo <dais...@gmail.com>
日期: Tue, 30 Jun 2009 17:13:48 +0800
當地時間: 2009年6月30日(星期二) 下午5時13分
主旨: Re: [TL] [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

*我的问题是对于其他操作系统或者windows上非微软系的,使用的是什么技术来解决这个问题的?

*COM不只是MS才有啊,读过《COM原理与应用》?

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 上午8時53分
寄件人: sagasw <sag...@gmail.com>
日期: Wed, 1 Jul 2009 08:53:04 +0800
當地時間: 2009年7月1日(星期三) 上午8時53分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

你确定那个叫做COM?我还知道一些呢,你要不要知道?
网景(火狐)还搞过一个xpcom还是comxp的,但是影响力薄弱,不如不提。

《COM原理与应用》当然读过,潘爱民根据com规范以及msdn写出来的一本书,那时候他还在北大研究所。
微软一开始还搞unix呢,可是微软现在的东西存在跨平台可能么?
(不要问我知不知道mono,我知道哦)

2009/6/30 Dai Shuo <dais...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Jiyong Xu  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 上午10時23分
寄件人: Jiyong Xu <xujiy...@gmail.com>
日期: Wed, 1 Jul 2009 10:23:40 +0800
當地時間: 2009年7月1日(星期三) 上午10時23分
主旨: Re: [TL] [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

单就你的邮件题目而言,建议你看看Essential COM的第一章,就会明了“c++的封装是语法层次而不是binary层的”的含义了。

你邮件正文里蓝色高亮的问题似乎是想讨论跨平台问题,可是你拿到的培训资料也不是在语言层面之外解决该问题的,所以和跨平台“跨”微软似乎扯不到一块儿去。

但要进一步讨论COM的话(这个会有点跨平台的问题),似乎又超出了你的问题的范围。

2009/6/30 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 上午10時32分
寄件人: sagasw <sag...@gmail.com>
日期: Wed, 1 Jul 2009 10:32:44 +0800
當地時間: 2009年7月1日(星期三) 上午10時32分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

对于c++封装是语法层而不是二进制的,前面Fei
Yan的回答让我学到不少,实际上这个问题当我写完了整个邮件,自己也算有了一定的领悟,于是在邮件里面留下的是另外一个问题,也就是解决方案是什么。

上网搜索了一下ARM有几篇文档专门介绍ABI。当然我们公司项目并不涉及到ABI,因为使用COM作为接口,而且都是Windows平台。

2009/7/1 Jiyong Xu <xujiy...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Dai Shuo  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 上午11時31分
寄件人: Dai Shuo <dais...@gmail.com>
日期: Wed, 1 Jul 2009 11:31:51 +0800
當地時間: 2009年7月1日(星期三) 上午11時31分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

呵呵,少安毋躁,要是我的回信让你不舒服,那不是我本意。

你的PPT给了解决方案:用单独方法new出对象。它不依赖微软、Windows,跨平台没有问题。
既然都有解决方案了,我不明白你为什么仍然要问 “其他操作系统使用什么技术解决这个问题”。

我提到COM和《COM原理与应用》,因为我觉得如果你理解了COM原理的话,就该理解C++“源码重用”的性质,COM“机器码重用”的性质,
还有COM规范,这一切都和操作系统没什么联系。并不是说PPT给的方法应用了COM。

2009/7/1 sagasw <sag...@gmail.com>


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Tiny fool  
檢視個人資料   翻譯為 已翻譯 (查看原文)
(2 位使用者)  更多選項 7月1日, 上午11時56分
寄件人: Tiny fool <tinyf...@gmail.com>
日期: Wed, 1 Jul 2009 11:56:40 +0800
當地時間: 2009年7月1日(星期三) 上午11時56分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

com的出现有两个大的原因,C++的封装没有二进制标准,以及C++没有动态链接的标准。其他类似com的机制也都是解决这个问题的。因为这两个问题的存在, 你无法用c++形式的接口去构建组件库,因为那会带来很多的麻烦。
楼主在顶楼应该误解了解决方案,CPerson* CreatePerson()应该是继承自纯虚接口,才可能起到作用。

为什么会这样呢,解释起来非常麻烦,我试试看给大家解释一下,有些概念也不那么清楚了。

如果你的类库只是在你的程序里面用代码形式来调用,那么这个问题很简单,任何语言都不会出现什么问题。编译器会解决绑定的问题,这里我就不细说了。

问题的产生是从我们使用二进制的库文件开始的。

1、首先我们看C库
一个C程序被编译成一个object文件以后,不管他动态还是静态链接,其实里面的C语言的结构就消失了,就变成了二进制结构。但是变量和函数都有符号链接。我 们引用错了库的时候经常可以看到编译器报符号链接找不到的错误,就是说如果没有相应的库,也就找不到相应的函数的符号链接,也就找不到函数的二进制代码,编译器 就不知道怎么去链接了。

object文件,实际上是可以重新定位的二进制代码,简单的说,就是所有的地址操作,都是相对于这个object的首地址的,编译到整个可执行文件的时候,这 些地址都会被定位成固定的地址。这个我们不去考虑了,跟我们要讨论的问题关系不大。

简化的说,就是我们写了一个c库,假设有

void test()
{
   printf("hello world!");

}

那么我们会有一个二进制的 object文件,里面是这个函数的二进制形式,有一个符号链接说明函数的位置
假设符号链接叫  __test  它指向 300050 这个地址(简化理解,我们就不考虑地址的重定向问题了,与我们讨论的问题无关)
(c的符号链接规范我也记不清了,就是个例子)

那么,有别的程序调用这个二进制的object,他实际上调函数test的时候,就把程序跳转到300050。

那么,问题出现了,你修改了
test函数,甚至整个库,重新编译这个库,你会发现test函数的位置可能会改变,你得到了新的库,你扔给用户,除了h文件以外,你需要给他你的源代码么?不 需要,因为虽然test的位置变了,但是编译器,本来就不是记死一个位置
300050,而是记住了符号链接  __test ,所以编译器,还是会把代码正确的链接起来。

动态链接,我就不说了,熟悉的人应该知道,原理也类似,C接口的动态链接库的逻辑也是找到一个符号链接,我们就可以把代码动态的拉到内存中了,道理是一样的。

2、那么我们看C++程序,这里面就出现了些问题。
如果我们静态链接程序,其实也没什么本质问题。
但是如果我们动态链接程序,一个类testdll他的实现在一个动态链接库testdll.dll里面(用win举例子,但是linux/unix都一样,C+ +的程序都是这样的)。

现在我们实现第一个版本的testdll,(c++语法不熟悉了,内链可以之么写吧?呵呵,大家明白就好了)
class testdll
{
public:
    int i;
    void test1()
    {
       print("test1");
    }
   void test2()
    {
       print("test2");
    }

}

你生成动态链接库以后,设置符号链接以后,你可以把所有的方法和成员都符号链接出来。
这样,你就有个符号链接表
testdll本身地址   xxxx001
testdll::i             xxxx002
testdll:: test1     xxxx009
testdll:: test2     xxxx010
然后你随着dll发布一个头文件一个lib,某人利用你的dll和头文件和lib写了个应用程序。

一切都很美好。

然而,这时候你发现你的dll设计有问题,你决定修改test1的实现,然后增加了test3,test4的实现,加入了一些private的成员。
class testdll
{
private:
   int x;
   int c;
public:
    int i;
    void test3()
    {
       print("test1");
    }
    void test1()
    {
       print("test1");
    }
   void test2()
    {
       print("test2");
    }
    void test4()
    {
       print("test1");
    }

}

这样新的符号链接表就出问题了,跟以前不一样了

testdll本身地址   xxxx001
testdll::i             xxxx005
testdll:: test3     xxxx010
testdll:: test1     xxxx013
testdll:: test2     xxxx015
testdll:: test4     xxxx017

这个大家能理解吧?实现不同的dll的里面的那些函数变量的位置自然不同了。但是注意,你刚才链接dll用的lib里面,符号链接是写死的,原来testdll ::
test2的地址是xxxx010,现在testdll::
test3才是。那么,你写的程序如果不重新编译的话,只更新dll的话,可怕的事情发生了,原来调用test2的地方,实际在调用test3。这个实验非常简 单,有vc或者其他开发环境的朋友实验一下就知道了,而且多半没有那么巧,往往是原来调用test2的地址,现在不是一个函数的入口,这样程序直接就死掉了。

有聪明人要说了,你说的是静态链接dll的时候,那时候你需要lib文件,当然地址死了,这样是不好的,我们可以动态的调用dll,用loadlibray函数 (unix/linux也都有类似的机制。)

你说的没错,但是问题依旧。

你的程序里面原来写testdll*
xxx=new testdll();然后你原来以为这个xxx占了几个字节等等,这些随着testdll的升级全都变了。你的程序还是会跑飞,只要你依赖了一点testdll 的一个实现版本。

在windows中出现com之前,所以,很多用c++写的dll,接口要用c包装一下,问题就在与此。当然我这里已经把问题简化无数倍了,Com提出还有一个 原因就是C接口的dll也有dll地狱问题,这个大家自己找资料去了,这已经是讨论了10几年的问题了,到处都有讨论,我就不说了。

3、现在说Com的实质是什么

说C++彻底是不行的,也是不对的。C++有一个二进制级别的接口方式。那就是纯虚类。实际上,所有现代面向对象语言都有纯虚类。java叫做interfac e,我最近用的Objective
C里面叫做protocol。

如果你的dll里面的类,所有要导出的方法都来自一个纯虚类的方法,那么这些方法的具体位置虽然每次编译都会变,但是如果你使用一个纯虚类的指针去调用这些方法 的话,首先会通过一个vtable,这个vtable是二进制兼容的,然后vtable里面的条目会指向这些方法的具体位置。这样不管你的实现如何升级,接口都 是二进制统一的,你改变组件的内部实现,就不需要程序开发者修改他们的程序了。

调用的起点是得到一个纯虚类指针,这就是为什么Com要求大家都必须从继承
IUnknown开始。所有的Com都从IUnknown开始,然后,你要在IUnknown的接口queryinterface告诉调用地用户,你知道哪些接 口,接口的定义是什么。这样用户的程序就可以找到这些接口的vtable,从而找到具体的实现方法的位置。有人说,虽然不同实现的,不同版本的实现中只要接口v table不变,二进制兼容性就不变。那么如果接口的vtable变了呢?这就是为什么Com不允许你更改一个接口的原因了。
*
*
如果你原来设计的xxx接口(实际上也就是那个纯虚类),现在发现功能不全,你想增加一个接口。那么如果你修改这个接口的话,你又破坏了二进制兼容性。Com的 逻辑是,要求你搞一个xxxV2,把新的接口函数放在那里面,所有发布过的接口都不允许改变,就是这个原因。
*
*
*
Com还有很多特性,但是前面说的二进制兼容性,就是他们的起点。至于引用计数,虽然对com很重要,但是实质上只是一个money的管理策略而已,并非com 的核心。注册表注册等等,也如是,可以说是必要的机制,但不是核心的逻辑。
*
*
*
*4、java的一个先进性在于,他的动态链接是虚拟机层面,或者说是语言层面的。所以他实现类似的功能无非这么复杂*
*
*
*5、大家对面向对象的认识有一个进化的过程*
*
最早大家认为面向对象是一个代码复用的好手段。后来我们发现接口复用越来越重要,当然这也跟需要复用的代码大多数都已经存在了有关。接口复用核心就是C++里面 的纯虚类,java的interface,objectivec里面的
protocol.*
*
*
*
*
*
*
2009/7/1 sagasw <sag...@gmail.com>

...

閱讀更多 »


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
Tiny fool  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 上午11時57分
寄件人: Tiny fool <tinyf...@gmail.com>
日期: Wed, 1 Jul 2009 11:57:00 +0800
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

累死了。。。

2009/7/1 Tiny fool <tinyf...@gmail.com>

...

閱讀更多 »


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
sagasw  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 下午12時30分
寄件人: sagasw <sag...@gmail.com>
日期: Wed, 1 Jul 2009 12:30:24 +0800
當地時間: 2009年7月1日(星期三) 下午12時30分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

有一些了解,有一些不了解,现在理解了,多谢tiny。

2009/7/1 Tiny fool <tinyf...@gmail.com>

...

閱讀更多 »


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
up duan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 下午1時14分
寄件人: up duan <fixo...@gmail.com>
日期: Wed, 1 Jul 2009 13:14:14 +0800
當地時間: 2009年7月1日(星期三) 下午1時14分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

2009/6/30 Fei Yan <skyscribe...@gmail.com>

> 也可以算作是ABI,但是问题本身和c++在ABI上边的缺陷没有必然联系吧。

> 一般c++ 特有的ABI缺陷引发的问题指代的应该是name mangling, vtable, virtual base, virtual
> inheritance, multiple inheritance, object alignment, data members' relative
> order.这些方面的问题一般是用户不应该关心的,但由于c++语言本身不能很好的提供可移植的方案,导致编译器实现细节的耦合。

你认为Java怎么解决这些问题的?

> 对于楼主这个问题,我认为不应该把其归结为ABI的问题,而是如何隐藏外部用户不关心的实现细节的问题;虽然推广说来,一切和实现细节相关的东西都能引申到AB I上来。即使是个ABI问题,那么也是c、c++都有的问题,
> 那么往底层说开来,也可以说是OS的ABI问题,这一个层面问题也是有不少的,像byte order, alignment, bit field等。

C的ABI由于历史原因 ,其实就是OS的ABI,这跟C++是不同的。

> 作为一类和底层直接打交道的语言,c/c++都不可避免类似的ABI不兼容的麻烦。Java、Python都没有类似的问题,因为它们自己做了一个中间层,把底 层操作都隔离起来了,用户看不到真正的字节;而Pimpl起到的作用是类似的,是语言之上的一个模拟,可以解决楼主关心的问题的主要矛盾,也就是:
> Foo() must know how much memory to allocate for the CPerson object p1.

A使用Java编写了一个X,B使用Java编写了一个Y,Y依赖于X,这儿并不是什么大不了的问题,因为无论是X还是Y,都是指针而已,拥有典型C++风格的 Pimpl只不过也是向Java一样,指针化了而已,这能解决上面的问题,但是还是不能解决依赖问题,因为C++的编译器强制要求依赖的组件必须被看到才能实施 编译,之所以这样,还是因为C++没有一个标准的ABI。
COM可以认为是一个阉割了的C++的ABI。


    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
qiaojie  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 下午1時26分
寄件人: qiaojie <qiao...@gmail.com>
日期: Wed, 1 Jul 2009 13:26:26 +0800
當地時間: 2009年7月1日(星期三) 下午1時26分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

>> 作为一类和底层直接打交道的语言,c/c++都不可避免类似的ABI不兼容的麻烦。Java、Python都没有类似的问题,因为它们自己做了一个中间层,把底 层操作都隔离起来了,用户看不到真正的字节;而Pimpl起到的作用是类似的,是语言之上的一个模拟,可以解决楼主关心的问题的主要矛盾,也就是:
>> Foo() must know how much memory to allocate for the CPerson object p1.

> A使用Java编写了一个X,B使用Java编写了一个Y,Y依赖于X,这儿并不是什么大不了的问题,因为无论是X还是Y,都是指针而已,拥有典型C++风格的 Pimpl只不过也是向Java一样,指针化了而已,这能解决上面的问题,但是还是不能解决依赖问题,因为C++的编译器强制要求依赖的组件必须被看到才能实施 编译,之所以这样,还是因为C++没有一个标准的ABI。
> COM可以认为是一个阉割了的C++的ABI。

你说的这个完全不是ABI的问题,而是C++没有metadata,其编译出来的模块不是自描述的。C有标准的ABI,但是他也没有metadata,不能解决 编译的依赖问题。
COM也不是什么阉割了的C++的ABI,我们可以用C写COM,也可以用VB, delphi,
.NET来写COM,COM是一个独立于C++的二进制模块规范。

    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
up duan  
檢視個人資料   翻譯為 已翻譯 (查看原文)
 更多選項 7月1日, 下午1時32分
寄件人: up duan <fixo...@gmail.com>
日期: Wed, 1 Jul 2009 13:32:39 +0800
當地時間: 2009年7月1日(星期三) 下午1時32分
主旨: Re: [TL] Re: [TL][c++]问题c++的封装是语法层次而不是binary层的,如何理解?

2009/7/1 qiaojie <qiao...@gmail.com>

>>> 作为一类和底层直接打交道的语言,c/c++都不可避免类似的ABI不兼容的麻烦。Java、Python都没有类似的问题,因为它们自己做了一个中间层,把底 层操作都隔离起来了,用户看不到真正的字节;而Pimpl起到的作用是类似的,是语言之上的一个模拟,可以解决楼主关心的问题的主要矛盾,也就是:
>>> Foo() must know how much memory to allocate for the CPerson object p1.

>> A使用Java编写了一个X,B使用Java编写了一个Y,Y依赖于X,这儿并不是什么大不了的问题,因为无论是X还是Y,都是指针而已,拥有典型C++风格的 Pimpl只不过也是向Java一样,指针化了而已,这能解决上面的问题,但是还是不能解决依赖问题,因为C++的编译器强制要求依赖的组件必须被看到才能实施 编译,之所以这样,还是因为C++没有一个标准的ABI。
>> COM可以认为是一个阉割了的C++的ABI。

> 你说的这个完全不是ABI的问题,而是C++没有metadata,其编译出来的模块不是自描述的。C有标准的ABI,但是他也没有metadata,不能解决 编译的依赖问题。

是么?metadata是什么?ABI又是什么? 或者说,metadata是关于什么的metadata?是不是关于object layout的?

COM也不是什么阉割了的C++的ABI,我们可以用C写COM,也可以用VB, delphi,

> .NET来写COM,COM是一个独立于C++的二进制模块规范。

嗯,我知道你可以用很多语言来写COM,但是我还是没有看出来这跟我说的“COM可以认为是一个阉割了的C++的ABI
”有什么抵触之处。COM是一个独立于C++的二进制模块规范,也不能否证“COM可以认为是一个阉割了的C++的ABI”啊。要不你再详细描述一番?

    回覆作者    轉寄  
您必須先登入才能張貼訊息。
若要張貼訊息,您必須先加入此群組
請在留言之前更新您訂閱設定網頁上的暱稱。
您沒有留言所需的權限。
1 - 25 個留言 (共 35 個)   較新 >
« 返回討論主題 « 較新的主題     較舊的主題 »

建立群組 - Google 網上論壇 - Google 首頁 - 服務條款 - 隱私權政策
©2009 Google