OOP:合法演员? [英] OOP: legal cast?

查看:46
本文介绍了OOP:合法演员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到了一些面向对象的编程位,而且我不知道他们是否合法。例如:


struct Object {

int field1;

int field2;

};


struct SubObject {

int field1; / *与Object * /

int field2相同; / *与对象相同* /


int subobject_field1;

int subobject_field2;

};


和一个演员用于引用超类 SubObject:


struct SubObject * subobject;


struct Object * parent =(Object *)subobject; / *合法演员? * /


然后使用parent-> field1等。这是否合法?调用UB或

更糟糕的是什么?


我也看过其他一些代码,其中恕我直言更正确,更优雅,

这是ANSI C中OOP的真实框架:


struct Class {

size_t size;

int( * ctor)(... etc)

};


struct String {

struct Class * class;

char * text;

};


等等。当然,是使用聪明的新()等功能。

我在pdf书中看过它,但我不能告诉你标题(pdf有

不是titlepage本身。)


谢谢和问候。

-

LuisAlbertoGiménez

JabberID: Si*******@bulmalug.ne​​t

GnuPG ID:0x3BAABDE1

解决方案

AlbertoGiménez写道:

我看过一些面向对象的编程位在那里,我不确定他们是否合法。例如:

struct Object {
int field1;
int field2;
};

struct SubObject {
int FIELD1; / *与Object * /
int field2相同; / *与Object相同* /

int subobject_field1;
int subobject_field2;
};

使用强制转换来引用超" SubObject:

struct SubObject * subobject;

struct Object * parent =(Object *)subobject; / *合法演员? * /

然后使用parent-> field1等。这是否合法?调用UB或
更糟糕的事情?


指针转换是合法的从某种意义上说,

结果可以重新转换为`struct SubObject *''并且

正常工作。转换本身不会造成任何麻烦。


但是,我认为它是非法的使用转换后的

指针来访问`struct SubObject''开头的`struct Object'''覆盖'

的字段。它会在我个人遇到的每个编译器上运行

就好了。

但据我所知,标准没有描述什么

行为将是 - 这使得行为未定义。

(6.5.2.3/5的保证仅适用于工会实例

包含结构,而不是独立的结构对象。)

技术就像驾驶速度超过速度限制:

技术上非法,但每个人都这样做。

我还看过其他一些代码,其中恕我直言更正确,更优雅,
这是ANSI C中OOP的真实框架:

struct Class {
size_t size;
int(* ctor)(... etc)
};

struct String {
struct Class * class;
char * text;
};


这很好。但是,深层继承层次结构将会产生深层嵌套的结构;这可以使符号相当麻烦:


/ * Strad扩展Violin extends String扩展类,

*和Fokker扩展Triplane扩展飞机

*扩展车辆扩展类

* /

struct Strad * strad = ...;

struct Fokker * fokker = ...;

size_t bufsize =(strad-> violin.string.class.size fokker-> triplane.aircraft.vehicle.class.size)


? strad-> violin.string.class.size

:fokker-> triplane.aircraft.vehicle.class.size;


如果您的代码启动看起来像这样,你可能想要
重新考虑你选择的实现语言。


-

Eric Sosman es*****@acm-dot-org.inva lid



Eric Sosman写道:

AlbertoGiménez写道:

我看过一些面向对象在那里编程位和
我不确定他们是否合法。例如:

struct Object {
int field1;
int field2;
};

struct SubObject {
int FIELD1; / *与Object * /
int field2相同; / *与Object相同* /

int subobject_field1;
int subobject_field2;
};

使用强制转换来引用超" SubObject:

struct SubObject * subobject;

struct Object * parent =(Object *)subobject; / *合法演员? * /

然后使用parent-> field1等。这是否合法?调用UB或
更糟糕的事情?



指针转换是合法的从某种意义上说,
结果可以重新转换为`struct SubObject *''并且
正常工作。转换本身不会带来任何麻烦。

但是,我认为它是非法的。使用转换后的
指针来访问`struct SubObject''开头的`struct Object''" overlaid"
字段。它会对我个人遇到的每个编译器都很好用,但据我所知,标准没有描述行为将会是什么 - 这会导致行为undefined。
(6.5.2.3/5的保证仅适用于包含结构的联合实例,而不适用于独立的结构对象。)
这种技术就像驾驶一样速度超过速度限制:
技术上非法,但每个人都这样做。




我既不能显示会产生UB的真实实现

实际上使这样的程序失败了,但这是因为我有限的

经验;然而,我可以很容易想象一个实现,当使用较小的

结构类型访问时,将使用b $ b覆盖较大结构的部分(让我们说有一个快速指令一次零和32 b / b
位是较小结构的最后一个成员是一个32位对齐的16位值和16位填充,其中较大的struct

有一个16位成员更多) - 所以我认为这就像驾驶

对抗高速公路上的方向 - 这是非常危险的,但是

有些人这样做了,有些甚至还活了下来。

我还看到了其他一些代码,其中恕我直言更正确,
优雅,这是ANSI C中OOP的真实框架:

struct Class {
size_t size;
int(* ctor)(... etc)
};

struct String {
struct Class * class;
char * text;
};



/ * Strad扩展Violin扩展String扩展类,
*和Fokker扩展Triplane扩展飞机
*扩展车辆扩展类
* /
struct Strad * strad = ...;
struct Fokker * fokker = ...;
size_t bufsize =(strad-> violin.string.class。尺寸
> fokker-> triplane.aircraft.vehicle.class.size)
? strad-> violin.string.class.size
:fokker-> triplane.aircraft.vehicle.class.size;

如果你的代码看起来像这样,你可能想要
重新考虑您选择的实施语言。

-
Eric Sosman
es ***** @ acm-dot-org.inva 盖子




Mark


AlbertoGiménez写道:

我在那里看到了一些面向对象的编程位


可以你告诉我们究竟在哪里在那里?

但我不确定他们是否合法。
例如:

struct Object {
int field1;
int field2;
};


你很困惑。对象是*不是*类型。

它是类型的*实例*。

struct SubObject {
int field1; / *与Object * /
int field2相同; / *与Object相同* /
int subobject_field1;
int subobject_field2;
};


这不是*子对象,因为它不是一个对象。

它甚至不是一个子类型。它只是另一个

[用户定义]类型,恰好有数据成员

与另一个[用户定义]数据类型同名。

和一个演员用于引用超类 SubObject:

struct SubObject * subobject;

struct Object * parent =(Object *)subobject; / *合法演员? * /

然后使用parent-> field1等。这是否合法?调用UB或更坏的东西?

我也看过其他一些代码,恕我直言,更正确,更优雅,这是一个真正的OOP框架在ANSI C中:

struct Class {
size_t size;
int(* ctor)(... etc)


什么这应该是什么?

};

struct String {
struct Class * class;
char * text;
};

等等。当然,是使用聪明的new()等功能。
我在pdf书中看过它,
但是我不能告诉你标题(pdf没有titlepage本身) 。
cat main.c
#include< stdio.h>


typedef struct Base {//超类型

int field1 ;

int field2;

}基础;


内联静态

Base Base_create(int f1 ,int f2){

基数;

base.field1 = f1;

base.field2 = f2;

返回基数;

}

内联静态

void Base_destroy(const Base * p){

/什么都不做

}

内联静态

int Base_field1(const Base * p){

返回p- > field1;

}

内联静态

int Base_field2(const Base * p){

返回p - > field2;

}

内联静态

int Base_fprintf(FILE * fp,const Base * p){

返回fprintf(fp,"%d%d",p-> field1,p-> field2);

}


typedef struct Derived {// sub type

base base;

int field1;

int field 2;

}派生;


内联静态

派生Derived_create(const Base * p,int f1,int f2){

派生衍生;

derived.base = * p;

derived.field1 = f1;

派生。 field2 = f2;

返回派生;

}

内联静态

void Derived_destroy(const Derived * p) {

//什么都不做

}

内联静态const

基础* Derived_base(const派生* p) {

return&(p-> base);

}

inline static

int Derived_field1( const派生* p){

返回p-> field1;

}

内联静态

int Derived_field2 (const派生* p){

返回p-> field2;

}

内联静态

int Derived_fprintf(FILE * fp,const Derived * p){

int total = Base_fprintf(fp,&(p-> base));

if(0< ;总计){

int local = fprintf(fp,"%d%d",p-> field1,p-> field2);

total =( 0< local)?总计+本地:本地;

}

返回总额;

}


int main( int argc,char * argv []){

const

基数= Base_create(13,14);

const

派生派生= Derived_create(& base,15,16);

Derived_fprintf(stdout,& derived);

fprintf(stdout," \\ \\ n");

Base_fprintf(stdout,Derived_base(& derived));

fprintf(stdout," \ n");

Derived_destroy(& derived);

Base_destroy(& base);

返回0;

}

gcc -Wall -std = c99 -pedantic -o main main.c
./main



13 14 15 16

13 14


1.使用typedef作为你的班级定义

,这样你就可以放弃多余的''struct''限定符。

2.为每种类型定义[伪]构造函数。

3.为每种类型定义析构函数并调用它们

ev如果他们实际上什么都不做的话。


C编程语言*不支持继承。

如果你想衍生来自另一个的新类型,

你应该制作一个超类型的对象

子类型的* first *数据成员

所以一个对象及其子对象具有相同的地址。

当你询问如何实现虚函数时,这将很重要



Hi, I''ve seen some object oriented programming bits out there and i''m
not sure if they''re legal. For example:

struct Object {
int field1;
int field2;
};

struct SubObject {
int field1; /* the same as Object */
int field2; /* the same as Object */

int subobject_field1;
int subobject_field2;
};

And a cast is used to reference the "superclass" of SubObject:

struct SubObject *subobject;

struct Object *parent = (Object *) subobject; /* legal cast? */

And then use parent->field1, etc. Is that cast legal? invokes UB or
something worse?

I''ve also seen some other code, whichi IMHO is more correct and elegant,
which is kind a real framework for OOP in ANSI C:

struct Class {
size_t size;
int (*ctor) (... etc)
};

struct String {
struct Class *class;
char *text;
};

And so on. Of course, is uses clever new() and so functions.
I''ve seen it in a pdf book, but I can''t tell you the title (the pdf has
not titlepage itself).

Thanks and greetings.
--
Luis Alberto Giménez
JabberID: Si*******@bulmalug.net
GnuPG ID: 0x3BAABDE1

解决方案

Alberto Giménez wrote:

Hi, I''ve seen some object oriented programming bits out there and i''m
not sure if they''re legal. For example:

struct Object {
int field1;
int field2;
};

struct SubObject {
int field1; /* the same as Object */
int field2; /* the same as Object */

int subobject_field1;
int subobject_field2;
};

And a cast is used to reference the "superclass" of SubObject:

struct SubObject *subobject;

struct Object *parent = (Object *) subobject; /* legal cast? */

And then use parent->field1, etc. Is that cast legal? invokes UB or
something worse?
The pointer conversion is "legal" in the sense that the
result could be re-converted to a `struct SubObject*'' and
work correctly. The conversion itself causes no trouble.

However, I think it''s "illegal" to use the converted
pointer to access the fields of a `struct Object'' "overlaid"
at the beginning of the `struct SubObject''. It will work
just fine on every compiler I personally have encountered,
but as far as I can see the Standard doesn''t describe what
the behavior will be -- which makes the behavior "undefined."
(The guarantees of 6.5.2.3/5 apply only to union instances
that contain structs, not to free-standing struct objects.)
The technique is like driving faster than the speed limit:
technically illegal, but Everybody Does It.
I''ve also seen some other code, whichi IMHO is more correct and elegant,
which is kind a real framework for OOP in ANSI C:

struct Class {
size_t size;
int (*ctor) (... etc)
};

struct String {
struct Class *class;
char *text;
};
This is fine. However, deep inheritance hierarchies will
produce deeply-nested structures; this can make the notation
rather cumbersome:

/* Strad extends Violin extends String extends Class,
* and Fokker extends Triplane extends Aircraft
* extends Vehicle extends Class
*/
struct Strad *strad = ...;
struct Fokker *fokker = ...;
size_t bufsize = (strad->violin.string.class.size fokker->triplane.aircraft.vehicle.class.size)


? strad->violin.string.class.size
: fokker->triplane.aircraft.vehicle.class.size;

If your code starts looking like this, you might want to
reconsider your choice of implementation language.

--
Eric Sosman
es*****@acm-dot-org.invalid



Eric Sosman wrote:

Alberto Giménez wrote:

Hi, I''ve seen some object oriented programming bits out there and i''m not sure if they''re legal. For example:

struct Object {
int field1;
int field2;
};

struct SubObject {
int field1; /* the same as Object */
int field2; /* the same as Object */

int subobject_field1;
int subobject_field2;
};

And a cast is used to reference the "superclass" of SubObject:

struct SubObject *subobject;

struct Object *parent = (Object *) subobject; /* legal cast? */

And then use parent->field1, etc. Is that cast legal? invokes UB or
something worse?



The pointer conversion is "legal" in the sense that the
result could be re-converted to a `struct SubObject*'' and
work correctly. The conversion itself causes no trouble.

However, I think it''s "illegal" to use the converted
pointer to access the fields of a `struct Object'' "overlaid"
at the beginning of the `struct SubObject''. It will work
just fine on every compiler I personally have encountered,
but as far as I can see the Standard doesn''t describe what
the behavior will be -- which makes the behavior "undefined."
(The guarantees of 6.5.2.3/5 apply only to union instances
that contain structs, not to free-standing struct objects.)
The technique is like driving faster than the speed limit:
technically illegal, but Everybody Does It.



I neither can show a real implementation that will produce UB which
actually makes such a program fail, but that''s rather due to my limited
experience; I can however easily imagine an implementation which will
overwrite portions of the larger struct when accessed with a smaller
struct type (let''s say there exists a fast instruction to zero out 32
bits at once and the last member of the smaller struct is an
32-bit-aligned 16-bit value plus 16 bit padding where the larger struct
has one 16-bit member more) - so I suppose this is rather like driving
against the direction on a highway - it is highly risky, nevertheless
some do it, and some even survive it.

I''ve also seen some other code, whichi IMHO is more correct and elegant, which is kind a real framework for OOP in ANSI C:

struct Class {
size_t size;
int (*ctor) (... etc)
};

struct String {
struct Class *class;
char *text;
};



This is fine. However, deep inheritance hierarchies will
produce deeply-nested structures; this can make the notation
rather cumbersome:

/* Strad extends Violin extends String extends Class,
* and Fokker extends Triplane extends Aircraft
* extends Vehicle extends Class
*/
struct Strad *strad = ...;
struct Fokker *fokker = ...;
size_t bufsize = (strad->violin.string.class.size
> fokker->triplane.aircraft.vehicle.class.size)
? strad->violin.string.class.size
: fokker->triplane.aircraft.vehicle.class.size;

If your code starts looking like this, you might want to
reconsider your choice of implementation language.

--
Eric Sosman
es*****@acm-dot-org.invalid



Mark


Alberto Giménez wrote:

I''ve seen some object oriented programming bits out there
Can you tell us exactly where "out there"?
but I''m not sure if they''re legal.
For example:

struct Object {
int field1;
int field2;
};
You are confused. An object is *not* a type.
It is an *instance* of a type.
struct SubObject {
int field1; /* the same as Object */
int field2; /* the same as Object */

int subobject_field1;
int subobject_field2;
};
This is *not* a sub object because it isn''t an object.
It isn''t even a subtype. It''s just another
[user defined] type that happens to have data members
with the same name as another [user defined] data type.
And a cast is used to reference the "superclass" of SubObject:

struct SubObject *subobject;

struct Object *parent = (Object *) subobject; /* legal cast? */

And then use parent->field1, etc. Is that cast legal? invokes UB or
something worse?

I''ve also seen some other code, which, IMHO, is more correct and elegant,
which is kind a real framework for OOP in ANSI C:

struct Class {
size_t size;
int (*ctor) (... etc)
What is this supposed to be?
};

struct String {
struct Class *class;
char *text;
};

And so on. Of course, is uses clever new() and so functions.
I''ve seen it in a pdf book,
but I can''t tell you the title (the pdf has not titlepage itself). cat main.c #include <stdio.h>

typedef struct Base { // super type
int field1;
int field2;
} Base;

inline static
Base Base_create(int f1, int f2) {
Base base;
base.field1 = f1;
base.field2 = f2;
return base;
}
inline static
void Base_destroy(const Base* p) {
// do nothing
}
inline static
int Base_field1(const Base* p) {
return p->field1;
}
inline static
int Base_field2(const Base* p) {
return p->field2;
}
inline static
int Base_fprintf(FILE* fp, const Base* p) {
return fprintf(fp, "%d %d", p->field1, p->field2);
}

typedef struct Derived {// sub type
Base base;
int field1;
int field2;
} Derived;

inline static
Derived Derived_create(const Base* p, int f1, int f2) {
Derived derived;
derived.base = *p;
derived.field1 = f1;
derived.field2 = f2;
return derived;
}
inline static
void Derived_destroy(const Derived* p) {
// do nothing
}
inline static const
Base* Derived_base(const Derived* p) {
return &(p->base);
}
inline static
int Derived_field1(const Derived* p) {
return p->field1;
}
inline static
int Derived_field2(const Derived* p) {
return p->field2;
}
inline static
int Derived_fprintf(FILE* fp, const Derived* p) {
int total = Base_fprintf(fp, &(p->base));
if (0 < total) {
int local = fprintf(fp, " %d %d", p->field1, p->field2);
total = (0 < local)? total + local: local;
}
return total;
}

int main(int argc, char* argv[]) {
const
Base base = Base_create(13, 14);
const
Derived derived = Derived_create(&base, 15, 16);
Derived_fprintf(stdout, &derived);
fprintf(stdout, "\n");
Base_fprintf(stdout, Derived_base(&derived));
fprintf(stdout, "\n");
Derived_destroy(&derived);
Base_destroy(&base);
return 0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main


13 14 15 16
13 14

1. Use the typedef for your class definitions
so that you can drop the superfluous ''struct'' qualifier.
2. Define [pseudo] constructors for each type.
3. Define destructors for each type and call them
even if they don''t actually do anything.

The C programming language does *not* support inheritance.
If you wish to "derive" a new type from another,
you should make an object of the super type
the *first* data member of the subtype
so that an object and its sub object have the same address.
This will be important later
when you ask about how to implement virtual functions.


这篇关于OOP:合法演员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆