0xAA55 发表于 2014-8-24 22:11:25

【面向对象】面向对象是一种思想,而不是一种编程语言

几乎任何语言都可以面向对象。汇编也可以。

我认为:把不同的事物,用编程语言描述清楚,然后对它们进行组织调用,就是面向对象。并不一定非得是C++的那种形式,任何语言都可以面向对象。
面向对象并不是把数据重新用结构体进行打包,而是把事物当成对象来看待。比如“向量”,就把它看成对象,对向量进行运算的程序专门写,而不是在用到向量的地方用float来表示。比如这样:typedef struct
{
    float x,y,z;
}Vector3,*Vector3P;这里定义了一个三维向量。这是对象吗?是的。而非面向对象的编程思路是什么呢?就像下面这样:float x,y,z;当然这个也可以被当成对象来编程,但是真正有说服力的是下面的代码。//代码演示:判断一个三维空间中的点是否在一个立方体的内部

//=============================================================================
//面向对象的思想
//-----------------------------------------------------------------------------
#include<math.h>
#include<memory.h>

//三维向量
typedef struct
{
    float x,y,z;
}Vector3,*Vector3P

//四维向量
typedef struct
{
    float x,y,z,w;
}Vector4,*Vector4P;

//三阶矩阵
typedef struct//矩阵可以当成“坐标系”来看待
{
    Vector3 xAxis;
    Vector3 yAxis;
    Vector3 zAxis;
}Matrix3x3,*Matrix3x3P;

//立方体
typedef struct
{
    Vector3   vSize;//长宽高
    Matrix3x3   mRotation;//旋转
    Vector3   vPosition;//位置
}Box3,*Box3P;

//向量乘三阶矩阵的函数
void Vec3MulTransposedMatrix3x3(Vector3P pVOut,Vector3P pVIn,Matrix3x3P pMatrix);

//=====================================
//判断点是否在立方体内部的函数
//是返回非零,否返回零
//-------------------------------------
int IsPointInBox
(
    Vector3P    pPoint, //点
    Box3P       pBox    //立方体
)
{
    Vector3   vTransformed;
   
    vTransformed.x=pPoint->x-pBox->vPosition.x;//相对坐标
    vTransformed.y=pPoint->y-pBox->vPosition.y;
    vTransformed.z=pPoint->z-pBox->vPosition.z;
   
    Vec3MulTransposedMatrix3x3(&vTransformed,&vTransformed,&(pBox->mRotation));//变换坐标位置
   
    if( fabs(vTransformed.x)<=pBox->vSize.x &&//如果经过变换的顶点在立方体内部
      fabs(vTransformed.y)<=pBox->vSize.y &&
      fabs(vTransformed.z)<=pBox->vSize.z)
      return 1;//返回非零
    else
      return 0;
}

//顶点乘三阶矩阵的函数
void Vec3MulTransposedMatrix3x3(Vector3P pVOut,Vector3P pVIn,Matrix3x3P pMatrix)
{
    Vector3 vTemp=
    {
      pVIn->x*pMatrix->xAxis.x+pVIn->y*pMatrix->xAxis.y+pVIn->z*pMatrix->xAxis.z,
      pVIn->x*pMatrix->yAxis.x+pVIn->y*pMatrix->yAxis.y+pVIn->z*pMatrix->yAxis.z,
      pVIn->x*pMatrix->zAxis.x+pVIn->y*pMatrix->zAxis.y+pVIn->z*pMatrix->zAxis.z
    };
    memcpy(pVOut,&vTemp,sizeof(Vector3));
}

//=============================================================================
//面向过程的思想
//-----------------------------------------------------------------------------
#include<math.h>
#include<memory.h>

//=====================================
//判断点是否在立方体内部的函数
//是返回非零,否返回零
//-------------------------------------
int IsPointInBox
(
    float   px,         //点
    float   py,
    float   pz,
    float   bx,         //立方体位置
    float   by,
    float   bz,
    float   mxx,      //立方体旋转矩阵
    float   mxy,
    float   mxz,
    float   myx,
    float   myy,
    float   myz,
    float   mzx,
    float   mzy,
    float   mzz,
    float   sizex,      //立方体尺寸
    float   sizey,
    float   sizez
)
{
    float tpx,tpy,tpz;//变换后的点
   
    px-=bx;//点相对立方体中心位置的点
    py-=by;
    pz-=bz;
   
    tpx=px*mxx+py*mxy+pz*mxz;//取得点实际相对立方体位置的点
    tpy=px*myx+py*myy+pz*myz;
    tpz=px*mzx+py*mzy+pz*mzz;
   
    if( fabs(tpx)<=sizex &&//如果经过变换的顶点在立方体内部
      fabs(tpy)<=sizey &&
      fabs(tpz)<=sizez)
      return 1;//返回非零
    else
      return 0;
}面向对象并不仅仅是将数据打包做成结构体给函数使用,关键是,我们把三维向量,用Vector3来表示,而不是用float x,y,z;来表示。我们把它看作是三维向量,并针对它进行编程。这才是面向对象的思想。

面向对象的好处是代码的可复用性高,可读性高,便于管理,你看上面的矩阵、向量的结构体和辅助函数等就可以拿去别的地方使用。而面向过程的要复用就麻烦多了。
实际上汇编也可以面向对象。。事实上绝大多数语言都可以面向对象。

这个时候可能会有人提出异议:假设我有个使向量单位化的函数Normalize,我定义void Normalize(Vector3*pVec);和我定义Vector3::Normalize();是有本质区别的,因为前者是调用别的函数来完成向量单位化,而后者是向量自己把自己单位化了。前者仍然是面向过程的思想,而后者才是真正的面向对象。
对此,我认为这只是一个形式上的区别。最终编译到二进制的时候,这两者的实现方式大同小异。
那么从语义上呢?
void Normalize(Vector3*pVec);确实是调用别的函数来完成向量单位化,有“面向过程”的嫌疑,但是反过来想,对于C语言,这样已经是最接近“面向对象”思想的写法了。
比起C++,C语言的优势很多。兼容性好,可移植性好,透明度高,都是它的优势。

有关C语言面向对象的实际应用,请大家参看libpng、libjpeg、giflib、libmp3、libFLAC、zlib、7z、lzma、freetype等各种国际开源项目的源码。

我晕 发表于 2014-9-3 15:33:28

原本的面向过程编程 是向函数传递结构体指针 让一个函数可以为同一结构体的多个变量服务
面向对象只不过是编译器做了这步 本质还是面向过程 将结构体理解成对象的数据 然后偷偷的把this指针用第一个参数传给成员函数了 也就是所有成员函数其实都带有一个隐藏参数
不过面向对象的基本特征不是那么好模拟的 继承和多态 不是面向过程语言简单就能做到的
这也就是人家说的 c++ java 才能真正的面向对象了...

0xAA55 发表于 2014-9-3 16:57:21

我晕 发表于 2014-9-3 07:33
原本的面向过程编程 是向函数传递结构体指针 让一个函数可以为同一结构体的多个变量服务
面向对象只不过是 ...

这是你对面向对象的定义吧?
个人觉得Linux的源码就是面向对象的。

我晕 发表于 2014-9-3 17:29:06

0xAA55 发表于 2014-9-3 16:57
这是你对面向对象的定义吧?
个人觉得Linux的源码就是面向对象的。

呵呵 我对面向对象的定义? 这应该算业内的看法吧
好吧 那你可以说每个人的定义都不同...

Linux的源码我只在下载时翻了一下 根本没看过 不过我觉得你这句话我应该能认同 的确有很多代码 看上去立刻就有一种感觉 应该就是你说的面向对象了

sizz 发表于 2014-11-21 14:13:35

额,其实我想说楼主的理解还是面向过程并没有面向对象。面向对象的最起码要具备三个特性,封装,继承和多态。就拿封装这一条来说,什么是封装?就是把数据和在数据上的操作封装起来,这就是一个对象,也就是说对象需要具有能对其自身进行操作的能力。比如在C++中定义一个struct Vector3D { float x; float y; float z;}; 假如现在要对这个向量规范化,那么可能会需要一个函数比如 void Normal(Vector3D &vec3D); 这就是早期的函数库思想,C语言中很多类似这样的库,这就是一种面向过程的思想。如果是面向对象,那么Vector3D中就应该包含对自身进行规范化的函数(我想不用多说,C++的struct是可以定义函数的),结果就是struct Vector3D {float x; float y; float z; void Normal(){函数定义} };,这样以后如果建立一个对象 Vector3D vec3D; 直接调用这个对象的函数 vec3D.Normal();就完成了规范化,这就是面向对象。当然封装的内容不仅仅这么多,继承和多态我就不说了,反正楼主所说的还是停留在面向过程阶段。

0xAA55 发表于 2014-11-21 14:20:40

sizz 发表于 2014-11-21 14:13
额,其实我想说楼主的理解还是面向过程并没有面向对象。面向对象的最起码要具备三个特性,封装,继承和多态 ...

那就是形式上的区别喽?你让我想起了COM类这种不伦不类的东西,如果让C语言使用,这个应该算面向对象还是面向过程呢?

此外多态可以通过转换结构体指针,使用union来实现,而继承也是如此。
另外如果要C语言实现你说的那种特性,那也可以,使用一些宏即可。

sizz 发表于 2014-11-21 14:35:43

这不是形式上的区别,那我们换个角度说,如果楼主你上面定义的Vector3结构体假如在某个编译器中已经被实现为一种基本类型,就和int bool float这类一样的基本类型,那么楼主帖子中两个函数实现又有什么区别呢,都是对基本类型的操作而已。其模式开始“用一个函数去操作另一个对象”,而不是“对象对自身进行操作”,这就是本质区别。

0xAA55 发表于 2014-11-21 14:40:26

sizz 发表于 2014-11-21 14:35
这不是形式上的区别,那我们换个角度说,如果楼主你上面定义的Vector3结构体假如在某个编译器中已经被实现 ...

从汇编的角度来看,“用一个函数去操作另一个对象”和“对象对自身进行操作”是一样的。
面向对象是一种思想而不是一种编程语言。请仔细看原文。
页: [1]
查看完整版本: 【面向对象】面向对象是一种思想,而不是一种编程语言