且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C ++对象模型

更新时间:2023-12-02 22:26:58

sumsin< su ******* @ gmail.comwrites:

来自''C ++对象模型内部''''Stanley B. Lippman''


''C ++对象模型的主要优势在于它空间和运行时间

效率。它的主要缺点是需要重新编译未经修改的

代码,该代码使用类的对象,其中已经添加,删除或修改非静态类类数据

成员。''


在这里我可以理解C ++对象模型的强度但是可以任何人

详细说明主要它的缺点。



想象一下你有:


class Widget:public Object {

private:

Rect bounds;

public:

virutal Rect& getBounds(void);

};


和Widget的一千个子类。

然后突然,用户重新询问小部件可能会在屏幕上以某个角度定向

。所以你添加一个字段:


class Widget:public Object {

private:

Rect bounds;

浮动角度;

public:

virutal Rect getBounds(void);

virutal float getAngle(void);

};


和lo,你必须重新编译所有数千个子类,因为

现在字段布局已经改变了,因为所有这些类。

与CLOS对比:


(defclass widget()((bounds:initarg:bounds:accessor bounds)))



#1 =#< STANDARD-CLASS WIDGET>


(defclass按钮(widget)((标题:initarg:title:accessor title)))



#1 =#< STANDARD-CLASS BUTTON>


(defvar * button-1 *(make-instance''button:bounds#(10 20 110 40):title" Test"))



* BUTTON-1 *


(inspect * button-1 *)



#< COMMON-LISP-USER :: BUTTON#x000334202008>:标准对象

类型:COMMON-LISP-USER :: BUTTON

0 [BOUNDS]:#< ARRAY T(4)#x000334201F10>

1 [TITLE]:测试

INSPECT--输入:h求助; :q返回REPL ---:q


我们创建了超类和子类,并创建了子类的实例。

突然,我们修改超类:


(defclass widget()((bounds:initarg:bounds:accessor bounds)(angle:initarg:angle:accessor angle:initform 0.0) ))



警告:DEFCLASS:类BUTTON(或其中一个祖先)正在重新定义,实例已过时

#1 =# < STANDARD-CLASS WIDGET:VERSION 1>


当然,子类的新实例将考虑到

的变化(无需进行任何操作子类本身):


(defvar * button-2 *(make-instance''button:bounds#(10 20 110 40):angle(/ pi 3) ):titlewith a angle))



* BUTTON-2 *


(inspect * button-2 *)



#< COMMON-LISP-USER :: BUTTON#x00033426C9A0>:标准对象

类型:COMMON-LISP-USER :: BUTTON

0 [BOUNDS ]:#< ARRAY T(4)#x00033426C878>

1 [ANGLE]:1.0471975511965977461L0

2 [TITLE]:有一个角度

INSPECT--输入:h寻求帮助; :q返回REPL ---:q

但更重要的是,子类的旧实例也已更新:


(inspect * button-1 *)



#< COMMON-LISP-USER :: BUTTON#x000334202008>:标准对象

类型:COMMON-LISP-USER :: BUTTON

0 [BOUNDS]:#< ARRAY T(4)#x000334201F10>

1 [ANGLE]: 0.0

2 [TITLE]:测试

INSPECT--输入:h寻求帮助; :q返回REPL ---:q


>



在CLOS中,甚至可以在定义超类之前定义(和编译)子类:


(defclass window(view)())



#1 =#< STANDARD-CLASS WINDOW:INCOMPLETE>


(defclass view(widget)())



#1 =#< STANDARD-CLASS视图>


(make-instance''window:bounds#(0 0 512 342))



# < WINDOW#x0003342E24C0>


(inspect *)



#< COMMON-LISP-USER :: WINDOW#x0003342E24C0> :标准对象

类型:COMMON-LISP-USER :: WINDOW

0 [BOUNDS]:#< ARRAY T(4)#x0003342E2400>

1 [ANGLE]:0.0

INSPECT--输入:h寻求帮助; :q返回REPL ---:q


>



-

__Pascal Bourguignon__


Pascal J. Bourguignon写道:

在CLOS中,[...]



这是比较苹果和橘子。 C ++基本上是一个宏汇编程序,

就像C一样。它只有比C更多的功能但是

操作的基本模式是相同的。编译完代码后,语言就消失了。

但是,它在这个角色中运行得很好(imho)。你不能将它与动态语言(lisp,smalltalk?,obj-C)进行比较,并且抱怨这个模型是多么灵活。 C ++的既定目标之一是保持与B'语言模型兼容的便携式汇编程序 - 而不是

引入任何(实质性)语言中间层程序之间

和硬件。为此,它工作得很好,但当然这带来了一些限制(以及优点)。


6月11日,4:56 pm,Michael DOUBEZ< michael.dou ... @ free.frwrote:

sumsinaécrit:

来自'C ++对象模型内部''''Stanley B. Lippman''


''C ++的主要优势对象模型是它的空间和运行时间b / b
效率。它的主要缺点是需要重新编译未经修改的

代码,该代码使用类的对象,其中已经添加,删除或修改非静态类类数据

成员。''


这里我可以理解C ++对象模型的强度但是任何人都可以

详细阐述了它的主要缺点。



缺点是对变更的影响:如果你改变了一个类(其成员)的

定义,你必须重新编译每一块

使用该类的代码,即使它没有被修改过。


这个缺点的解决方案是pimpl习语。


-

Michael



你的意思是我添加任何:

- 静态数据成员和/或

- 非静态成员函数和/或

- 静态成员函数和/或

- 虚拟成员函数,即使这样,未经修改的代码也会重新编译!


但这不是我认为的陈述的意思。


From ''Inside the C++ Object Model'' by ''Stanley B. Lippman''

''The primary strength of the C++ Object Model is its space and runtime
efficiency. Its primary drawback is the need to recompile unmodified
code that makes use of an object of a class for which there has been
an addition, removal, or modification of the nonstatic class data
members.''

Here I can understand the strength of C++ object model but can anybody
elaborate the primary drawback of it.

sumsin <su*******@gmail.comwrites:
From ''Inside the C++ Object Model'' by ''Stanley B. Lippman''

''The primary strength of the C++ Object Model is its space and runtime
efficiency. Its primary drawback is the need to recompile unmodified
code that makes use of an object of a class for which there has been
an addition, removal, or modification of the nonstatic class data
members.''

Here I can understand the strength of C++ object model but can anybody
elaborate the primary drawback of it.

Imagine you have:

class Widget :public Object {
private:
Rect bounds;
public:
virutal Rect& getBounds(void);
};

and a thousand of subclasses of Widget.
And suddenly, the user requets that the widgets may be oriented by
some angle on the screen. So you add a field:

class Widget :public Object {
private:
Rect bounds;
float angle;
public:
virutal Rect getBounds(void);
virutal float getAngle(void);
};

and lo, you have to recompile all the thousand of subclasses, because
now the field layout has changed, for all these classes.
Contrast that with CLOS:

(defclass widget () ((bounds :initarg :bounds :accessor bounds)))

#1=#<STANDARD-CLASS WIDGET>

(defclass button (widget) ((title :initarg :title :accessor title)))

#1=#<STANDARD-CLASS BUTTON>

(defvar *button-1* (make-instance ''button :bounds #(10 20 110 40) :title "Test"))

*BUTTON-1*

(inspect *button-1*)

#<COMMON-LISP-USER::BUTTON #x000334202008>: standard object
type: COMMON-LISP-USER::BUTTON
0 [BOUNDS]: #<ARRAY T (4) #x000334201F10>
1 [TITLE]: "Test"
INSPECT-- type :h for help; :q to return to the REPL ---:q

We created the superclass and a subclass, and made an instance of the subclass.
Suddenly, we modify the superclass:

(defclass widget () ((bounds :initarg :bounds :accessor bounds) (angle :initarg :angle :accessor angle :initform 0.0)))

WARNING: DEFCLASS: Class BUTTON (or one of its ancestors) is being redefined, instances are obsolete
#1=#<STANDARD-CLASS WIDGET :VERSION 1>

Of course new instances of the subclasses will take into account the
changes (nothing has to be done about the subclasses themselves):

(defvar *button-2* (make-instance ''button :bounds #(10 20 110 40) :angle (/ pi 3) :title "At an angle"))

*BUTTON-2*

(inspect *button-2*)

#<COMMON-LISP-USER::BUTTON #x00033426C9A0>: standard object
type: COMMON-LISP-USER::BUTTON
0 [BOUNDS]: #<ARRAY T (4) #x00033426C878>
1 [ANGLE]: 1.0471975511965977461L0
2 [TITLE]: "At an angle"
INSPECT-- type :h for help; :q to return to the REPL ---:q
But what''s more, the old instances of the subclasses have been updated too:

(inspect *button-1*)

#<COMMON-LISP-USER::BUTTON #x000334202008>: standard object
type: COMMON-LISP-USER::BUTTON
0 [BOUNDS]: #<ARRAY T (4) #x000334201F10>
1 [ANGLE]: 0.0
2 [TITLE]: "Test"
INSPECT-- type :h for help; :q to return to the REPL ---:q

>


In CLOS, it''s even possible to define (and compile) subclasses before having defined the superclass:

(defclass window (view) ())

#1=#<STANDARD-CLASS WINDOW :INCOMPLETE>

(defclass view (widget) ())

#1=#<STANDARD-CLASS VIEW>

(make-instance ''window :bounds #(0 0 512 342))

#<WINDOW #x0003342E24C0>

(inspect *)

#<COMMON-LISP-USER::WINDOW #x0003342E24C0>: standard object
type: COMMON-LISP-USER::WINDOW
0 [BOUNDS]: #<ARRAY T (4) #x0003342E2400>
1 [ANGLE]: 0.0
INSPECT-- type :h for help; :q to return to the REPL ---:q

>

--
__Pascal Bourguignon__


Pascal J. Bourguignon wrote:
In CLOS, [...]

That''s comparing apples and oranges. C++ is basically a macro assembler,
just like C. It only has more features than C but the basic mode of
operation is the same. Once the code is compiled, the language is gone.
However, it works pretty well in that role (imho). You can''t compare
that to a dynamic language (lisp, smalltalk?, obj-C) and complain how
inflexible that model is. One of the stated goals of C++ is to remain
compatible with C''s language model as a portable assembler -- not to
introduce any (substantial) language middle layer between the program
and the hardware. For that, it works quite ok but of course this brings
some limitations (aswell as advantages).


On Jun 11, 4:56 pm, Michael DOUBEZ <michael.dou...@free.frwrote:
sumsin a écrit :
From ''Inside the C++ Object Model'' by ''Stanley B. Lippman''

''The primary strength of the C++ Object Model is its space and runtime
efficiency. Its primary drawback is the need to recompile unmodified
code that makes use of an object of a class for which there has been
an addition, removal, or modification of the nonstatic class data
members.''

Here I can understand the strength of C++ object model but can anybody
elaborate the primary drawback of it.


The drawback is in terms of impact upon change: if you change the
definition of a class (its members) ,you have to recompile every piece
of code that uses this class even if it has not been modified.

A solution to this drawback is the pimpl idiom.

--
Michael

You mean if I add any:
- static data member and/or
- non-static member function and/or
- static member function and/or
- virtual member function, even then also the unmodified code will
recompile!!

But that is not the meant of statement I think.