| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3953 人关注过本帖, 1 人收藏
标题:数据抽象
只看楼主 加入收藏
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
1、(1)这句话在任何时候都有可能被遗忘,我以前也经常这样,导致我几天都没找到问题所在。。。
// 这个你忘不忘,我认为无所谓

2、tp的值可能被修改,特别是那些认为自己聪明的程序员,想利用它达到某些特殊的效果。
还有很多程序员不愿意使用stack.GetTopPointer和stack.GetBottomPointer来获得顶和底指针,而喜欢直接用stack.tp和stack.storage,看起来没有任何错误,因为这两个字段可以直接使用,而且节省函数调用开销。想一想,如果有一点我修改了实现,我认为用tp作为栈顶指针的名字是不好的,storage也如此,那么任何直接使用了tp和storage的代码都需要重新修改。并且我认为C并不能做到面向对象,只能做到不完全的基于对象。
//
确实,很多程序员不愿意使用 stack.GetTopPointer,而喜欢直接用stack.tp和stack.storage
你知道直接用 stack.tp 和stack.storage 的优点在哪里吗?这样直接仿问来的简单
c 语言可以强制程序员 使用接口仿问变量,你把那个 stack 结构体从 .h 移到 .c里面去,stack结构体对外部就是不可见的,
就成了一个 ADT。

能不能做到面向对象,得知道 对象是什么?
对象是一个 数据结构的 实例
数据结构就是你上面说的 数据和方法的绑定,那个.h 和 .c 合起来就是一个数据结构

我就是真命天子,顺我者生,逆我者死!
2012-02-07 14:49
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
我不太喜欢别人讨论 c,祝楼主 c++旅途愉快...

我就是真命天子,顺我者生,逆我者死!
2012-02-07 15:05
zaixuexi
Rank: 12Rank: 12Rank: 12
来 自:上海
等 级:火箭侠
威 望:8
帖 子:858
专家分:3233
注 册:2010-12-1
收藏
得分:0 
回复 21楼 BlueGuy
不可见用typedef

技术问题,请不要以短消息方式提问
2012-02-07 15:42
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 21楼 BlueGuy
在C中,初始化被遗忘导致错误是程序界公认的,不仅是我可能犯这个错误。我知道版主喜欢OpenGL,那么我们就来画一些图形吧:
1、圆形(Circle)
2、正方形(Square)
3、三角形(Triangle)

实现画(Draw)这些形状和清除(Erase)这些形状。

C版本的:
程序代码:
#include <stdio.h>

enum Shape { CIRCLE, SQUARE, TRIANGLE } currentShape;

void DrawCircle() { printf("Draw a circle.\n"); }
void EraseCircle() { printf("Erase a circle.\n"); }

void DrawSquare() { printf("Draw a square.\n"); }
void EraseSquare() { printf("Erase a square.\n"); }

void DrawTriangle() { printf("Draw a triangle.\n"); }
void EraseTriangle() { printf("Erase a triangle.\n"); }

void Draw() {
   switch (currentShape) {
   case CIRCLE:   DrawCircle();   return;
   case SQUARE:   DrawSquare();   return;
   case TRIANGLE: DrawTriangle(); return;
   default: return; // Error here
   }
};

void Erase() {
   switch (currentShape) {
   case CIRCLE:   EraseCircle();   return;
   case SQUARE:   EraseSquare();   return;
   case TRIANGLE: EraseTriangle(); return;
   default: return; // Error here
   }
}

int main(void) {
   currentShape = TRIANGLE;
   Draw();
   currentShape = CIRCLE;
   Draw();
   currentShape = SQUARE;
   Draw();

   // Do other things...

   currentShape = TRIANGLE;
   Erase();
   currentShape = CIRCLE;
   Erase();
   currentShape = SQUARE;
   Erase();

   return 0;
} /* Output:
Draw a triangle.
Draw a circle.
Draw a square.
Erase a triangle.
Erase a circle.
Erase a square.
*/
我设置了一个状态机(currentShape)来表示当前形状,当调用Draw之前必须设置需要绘制的形状,然后Draw通过判断形状来调用对应的函数,Erase函数也一样。
我们来看看C++版本的:
程序代码:
#include <iostream>
using namespace std;

class Shape {
public:
   virtual void draw() = 0;
   virtual void erase() = 0;
};

class Circle : public Shape {
public:
   void draw() { cout << "Draw a circle." << endl; }
   void erase() { cout << "Erase a circle." << endl; }
};

class Square : public Shape {
public:
   void draw() { cout << "Draw a Square." << endl; }
   void erase() { cout << "Erase a Square." << endl; }
};

class Triangle : public Shape {
public:
   void draw() { cout << "Draw a Triangle." << endl; }
   void erase() { cout << "Erase a Triangle." << endl; }
};

void draw(Shape& shape) { shape.draw(); }

void erase(Shape& shape) { shape.erase(); }

int main() {
   Circle   c;
   Square   s;
   Triangle t;

   draw(c);
   draw(s);
   draw(t);

   // Do other things...

   erase(c);
   erase(s);
   erase(t);
} /* Output:
Draw a circle.
Draw a Square.
Draw a Triangle.
Erase a circle.
Erase a Square.
Erase a Triangle.
*/
在这个版本中,draw和erase并没有判断,参数都被向上转型(Upcasting)到了他们的基类Shape,并且可以知道Shape的draw和erase函数都使用了后期绑定(虚函数),调用时它会自动计算到正确的函数地址,并调用这个正确的函数。

如果我现在想增加一个梯形(Trapezoidal),C版本需要这样改:
在枚举Shape中增加一个成员TRAPEZOIDAL,然后分别为Trapezoidal实现Draw和Erase函数,然后在Draw函数的switch中增加一个TRAPEZOIDAL判断条件,最后在Erase函数的switch中增加一个TRAPEZOIDAL判断条件。

在C++中需要这样改:
增加一个梯形类Trapezoidal,它继承至Shape,实现该类的画(draw)和擦除(Erase)函数。

区别是显而易见的,其实这才是真正的面象对象:
1、继承建立公共接口。
2、后期绑定。
基于对象是指:
1、数据结构与函数捆绑(在C中可以通过在结构中增加函数指针域来完成)。
2、构造(创建这个对象时就初始化,这在C中只能靠自己)。
3、继承(代码重用,复用接口,建立类层次)。
C似乎只能勉强支持第1点,所以我说它只能完成不完全的基于对象。

[ 本帖最后由 lz1091914999 于 2012-2-7 16:54 编辑 ]

My life is brilliant
2012-02-07 16:49
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 22楼 BlueGuy
版主,这你就误会了,没有C会有C++吗?我在这里只是想分享一下我以前学习的经验,并不是在贬低C,我只想讨论一下用C做设计的局限性。众所周知,用C写算法是再好不过的,但做设计,C++的确比C好,找准机会用适当的东西才是最重要的,也祝版主C旅途愉快!

My life is brilliant
2012-02-07 17:01
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
你举的例子没有用到 继承的概念, 你试试用 c 语言模拟一下继承的机制。

你的构造函数设计的有一点点问题,如果你的 对象是在堆中分配的话,是可以把初始化代码填到构造函数里
Java 一直都是这样做的,c 通常也是这样做的。

c 可以很好的支持 单一继承。
c 语言不支持 RTTI,必须得依靠 类型检测。

c 的最大优点就是简单,
c++ 的最大缺点就是繁琐

从编程语言排行榜上看,c++ 是一门呈直线没落的语言,说明 c++ 还是有很多问题的...

我就是真命天子,顺我者生,逆我者死!
2012-02-07 17:30
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 26楼 BlueGuy
我以前没接触过ADT,这里能不能请教一下版主呢?而且我很想知道如何用C来做单根继承呢?谢谢啦!

My life is brilliant
2012-02-07 17:37
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:0 
回复 26楼 BlueGuy
其实面向对象最主要的是,继承和多态,比如在Thinking in C++中有一节是这样说的:
Evolution of C++ programmers (C++程序员的演变)
C programmers seem to acquire C++ in three steps.First,as simply a "better C",because C++ forces you to declare all functions before using them and is much pickier about how variables are used.You can often find the errors in a C program simply by compiling it with a C++ compiler.

The second step is "object-based"C++.This means that you easily see the code organization benefits of grouping a data structure together with the functions that act upon it, the value of constructors and destructors,and perhaps some simple inheritance.Most programmers who have been working with C for a while quickly see the usefulness of this because,whenever they create a library,this is exactly what they try to do.With C++,you have the aid of the compiler.

You can get stuck at the object-based level because you can quickly get there and you get a lot of benefit without much mental effort.It's also easy to feel like you're creating data types - you make classes and objects,you send messages to those objects, and everything is nice and neat.

But don't be fooled.If you stop here,you're missing out on the greatest part of the language, which is the jump to true object-oriented programming.You can do this only with virtual functions.

Virtual functions enhance the concept of type instead of just encapsulating code inside structures and behind walls,so they are without a doubt the most difficult concept for the new C++ programmer to fathom.However,they're also the turning point in the understanding of object-oriented programming.If you don't use virtual functions,you don't understand OOP yet.

My life is brilliant
2012-02-07 18:02
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
回复 28楼 lz1091914999
其实,面向对象 是忽悠人的迂腐理论
什么时候你认清了这个事实,你就理解了面向对象

我就是真命天子,顺我者生,逆我者死!
2012-02-11 10:58
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
我希望 面向对象 这些条条框框不会成为你学习 或是 工作的障碍

我就是真命天子,顺我者生,逆我者死!
2012-02-11 11:09
快速回复:数据抽象
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.014396 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved