用C ++思考?

时间:2010-06-28 04:45:15

标签: c++ c

我使用的编程语言是Java。我一直在转向C ++,这在某种程度上很不稳定。 “rock-ness”不在学习中,而是更多地沿着“Thinking in C ++”。

我见过很多人说你应该先学习C(我在技术上已经知道了),然后我看到人们说不要跳过C并直接进入C ++。这又不是一个“学习”问题;这是一个“思考”问题;我知道C ++的语法,我在C ++中知道OOD等等。

例如SDL中的这段代码我可以解释它,好像我知道它,但我不能真正“利用”指针:

SDL_Surface* hello = NULL;

我应该用C语言进行编程才能“使用”吗?如果我从来没有使用像Java这样的语言,我该怎么做才能习惯指针?

11 个答案:

答案 0 :(得分:13)

指针确实很重要,C和C ++也有这个概念。

但是C ++不只是带有对象的C语言。

您可以从Bruce Eckel的Planet PDF下载两本免费书籍Thinking in C++(第一卷和第二卷),它们将真正帮助您理解C ++。

许多C ++也是工具包,无论是标准库(std)还是MFC,或者来自反粒几何库的类等等。这也有所作为。

如果您需要C ++,请选择C ++。首先学习C就像学习西班牙语,这样你就可以学习葡萄牙语,而不仅仅是学习葡萄牙语。

答案 1 :(得分:13)

如果您理解语法,那么在语言中成为“流利”的唯一方法就是使用它。

使用C是保持简单并接近“金属”的好方法,但它与C ++不同,所以如果你希望使用C ++,我最终会建议使用C ++。 (即如果你想要精通意大利语,不要学习拉丁语,尽管拉丁语会给你很多见解,两种语言是不同的野兽,所涉及的思维过程也相应不同)

指针很容易,一旦你“得到”它们。使用指针时的一个好主意是使用“p”前缀表示法。对于每个指针(间接级别),在变量名称的前面添加一个“p”,以提醒您它是一个指针:

Vehicle vehicle     = an actual vehicle
Vehicle *pVehicle   = a pointer to a Vehicle
Vehicle **ppVehicle = a pointer to a pointer to a Vehicle

要访问车辆,您必须为每个指针取消引用一次,即:

vehicle.SetName("Ford Focus");       // Directly access an object instance
(*pVechicle).SetName("Ford Focus");  // Dereference once
(**ppVehicle).SetName("Ford Focus")  // Dereference twice

有三种解除引用的方法(只是产生相同代码的不同语法):

(*pVehicle).DoSomething()
pVehicle->DoSomething()
pVehicle[0].DoSomething()

当您对指针使用算术时,它们以车辆单位运行,而不是以字节为单位,即

pVehicle++;   // Move to the next vehicle record, not just the next byte

最后,每个

pVehicle = new Vehicle

您需要平衡代码:

delete pVehicle;
pVehicle = NULL;

(编辑)哦,差点忘了最重要的一个:在尝试使用之前,请务必检查指针是否有效!

if (pVehicle != NULL)
    ...use pVehicle

我发现“p”符号非常有价值,因为你永远不会忘记某些东西是指针,p的数量告诉你需要多少个解引用。一旦我采用它,我就停止编写NULL取消引用/访问违规错误。

这就是你需要知道的关于指针的所有信息。现在你只需要使用它们来获得流畅性。

答案 2 :(得分:6)

我认为学习C不会有助于你在c ++中的“思考”。通常,你只需要习惯某些C ++概念及其有用的原因。

关键的是智能指针(更常见的是RAII)和非常大的模板。

还要记住,c ++是一种多范式语言,而不是严格的OOP。通常,最好的解决方案根本不是面向对象的(STL是模板比基于对象更好的设计的一个很好的例子)。

答案 3 :(得分:6)

  

我应该用C编程来获取   “习惯了”这个?

不,你不应该。当C ++主要被认为是“C但带有类”时,C曾经是对C ++的一个很好的介绍。 C ++从这种思维方式发展到如此之多,以至于在C ++中编写C代码会导致非常糟糕的C ++代码。

  

我应该怎样做才能适应   指针,如果我从来没有使用过它们   来自Java等语言?

知道如何在C ++中使用指针意味着几个关键领域(你应该一个接一个地学习它们):

  • 指针算术(添加和减少指针和整数,零指针,指针和数组的使用,指针操作);这是C ++与C共享的部分。

  • 指向函数的指针(此部分也与C共享)。

  • 指针转换(static_cast,dynamic_cast,...)。这部分是C ++特定的。您还可以定义自己的演员类型并稍微进行实验(并以boost :: lexical_cast为例)。

  • 指向成员对象和成员函数的指针。

  • 用于指针和各种智能指针实现的RAII:循环链接指针,引用计数指针(boost :: shared_ptr),唯一指针(std :: auto_ptr),作用域指针。

  • 在函子类中包装函数指针(参见std :: tr1 :: function或boost :: function)。

  • 对象引用以及它们如何与指针不同;在哪里使用引用以及在何处使用指针。

  • 指针和迭代器之间的相似之处。

  • 使用operator*operator->来模拟对象的指针式行为(以及何时不滥用此行为)。

  • 指针和const ness / mutability:指针,const指针,指向const值的指针和指向const值的const指针(以及何时使用每个指针)之间的区别是什么,和类似的使用可变指针。

当前C ++中的最佳实践建议不要在代码中使用指针,除非它们由代码自动管理(例如通过RAII)。

答案 4 :(得分:3)

你知道,有一本非常受好评的书实际上名为“Thinking in C++”:)更好的是,它是免费的!它应该可以帮助你在更深层次上指出诸如指针之类的东西 - 它明确地适应了它。

答案 5 :(得分:3)

编程语言只是一种工具。最重要的是,你知道的越多越好。 C是学习IMO的一种非常好的语言,出于同样的原因,堆栈溢出的联合创始人之一(Joel Spolsky)在本文中提到:http://www.joelonsoftware.com/articles/CollegeAdvice.html。在我毕业之前,我读了这篇文章,并且在我毕业之前提出了关于学习C的建议。

在一天结束时,用任何语言编写的软件都在(或通过)计算机芯片上运行。理解(如果你想成为一个'好'的程序员)非常重要的是你使用的任何语言所使用的机制的成本(在cpu时间和程序员时间内)。在某些情况下,高级语言非常适合程序员,因为它们允许您比C等低级语言更快地实现强大的最终用户功能。但是,低级语言通常可以提供更好的性能。作为程序员,你唯一需要考虑的是“这项工作的正确工具是什么?”你不要用锤子在螺丝上驱动,等等插入其他类似的炊具切刀等等。

高级语言倾向于隐藏程序员的一件事是指针。指针是一个非常重要的概念,熟悉您是否使用隐藏它们的语言进行编程。 C是学习指针(或C ++)的好语言。递归是另一个重要的,但我认为任何语言都不能真正隐藏这个概念......它是一个通用的问题解决概念,而指针更像是一个机械细节。

最后,我的学位实际上并不需要我参加编译器课程。我本可以避开它,但由于它是最臭名昭着的课程之一,我觉得如果我不接受它,我就不会那么人了。我的成绩确实非常糟糕,但是我在课堂上学到了很多重要的东西,这非常值得我接受GPA的谚语摇滚。如果您了解编程语言是如何实际实现的,那么与仅知道如何使用“语言X”相比,您将拥有巨大的优势。任何编程语言都需要时间来学习,即使你确实拥有世界上所有的基础知识。随处可见的混蛋将试图告诉你学习“语言X”是多么容易,但这些人通常只是不安全,并希望通过表现得像他们天生具有用'语言X'编程的能力一样让自己感觉良好。他们真的花了很多时间学习它。没有人天生就知道这些东西,只是给自己时间学习,但要聪明一点。开发一种学习新语言的系统方法(我的策略总是从用语言写“你好世界”开始)你会做得很好。结束了。

答案 6 :(得分:2)

我说专注于你遇到问题的主题。指针在C和C ++中大部分都是相同的,因此选择对您最有帮助的资源。

我的女朋友在开始使用C ++时遇到了麻烦,她推荐了一本名为Understanding Pointers in C的书。

关于“用C ++思考”的指针有什么用?

  • 指针可以设置为NULL(即0)。这对于可能具有值的情况进行建模非常有用。
  • 指针可以被重新命名为新对象 - 而不是引用,只能初始化一次,初始化后不能重新命名。
  • 指针可以隐式上传(从派生类到基类)。
  • 指针可以从基类明确地向下转换为派生类。您可以使用static_cast 执行此操作,如果您碰巧知道派生类的真正含义!人们通常使用dynamic_cast执行此操作以进行额外的运行时健全性检查。
  • 如果您想将指针传递给某人但您不希望他们知道您指向的对象类型,则可以将指针强制转换为void*。换句话说,指针可以变得不透明。
  • 指针和数组几乎相同。

以下是一些与C ++和C独有的指针有关的事情:

  • C ++具有引用的概念,可以在许多使用指针的情况下使用,但是比指针更难搞(取消引用无效地址)。
  • C ++有成员函数指针的概念,它与指向函数的指针略有不同,C也有。
  • 在C ++中,您可以定义自己的对象,其行为类似于指针 - 即您可以使用*一元运算符取消引用。 C ++库使用此功能来实现智能指针,它们是一类完整的对象,其行为类似于指针,但也内置了一些访问或所有权管理层。

答案 7 :(得分:1)

在我看来,C ++作为一种语言是如此复杂,以至于对它的理解仍在不断发展。我还在发现新的编程技巧。 C不再是对C ++的一个很好的介绍。事实上,在C语言中过于沉浸会教会你不好的C ++习惯,而且会让你对C ++中一些非常有用的东西视而不见。例如,在C ++中,我认为指针比在Java中更重要,但不如C中那么多。

没有可以阅读的魔法书或者你可以学习用C ++思考的公式。你必须练习这些概念。编写自己的程序,使用它们,即使它们只是玩具。

以下是我应该练习并逐渐习惯使用的重要C ++想法的个人列表:

  • 使用swap(在C ++ 0x中使用移动构造函数和赋值运算符)来编写具有强异常保证的代码。
  • 模板元编程(模板基本上是C ++中的一种函数式语言,输出的是C ++程序)。
  • RAII idiom(RAII代表资源获取是初始化) - 这是C ++中与Java完全不同的东西,对理解非常重要。
  • 并且,与RAII相关,非常原始类型的对象是在不使用new的情况下常规创建的概念。您可以直接在堆栈上创建对象,也可以通过包含而不是通过引用来引用它们。这与Java有着巨大但微妙的区别。
  • 迭代器 - 大多数情况下非Javaesque指针的使用已经变成了什么
  • 实际上,没有用作迭代器的指针与Java中非原始类型的变量(即从Object派生的东西)相同,除了缺少垃圾收集。

答案 8 :(得分:1)

这个问题与中的思考无关。你只需要学习更多的C ++。你已经了解Java是件好事,因为Java中的所有重要内容都直接存在于(并且实际上是借鉴或受其影响)C ++,所以你只需要学习更多的C ++来学习如何将这些Java设计思想“映射”到C ++实现。

不要学习C来学习C ++。这是一个愚蠢的神话。它们是两种不同的语言。学习C ++学习C ++。

答案 9 :(得分:0)

如果你真的想要掌握指针概念,我会建议这本书:

通过Yeshwant Kanitkar了解C中的指针

它非常清晰,有组织的书,可以让您从头开始深入了解指针指针的应用程序。

答案 10 :(得分:0)

如果您每天都在使用C ++项目,那么您可能已经习惯了使用指针。知识和反复出现的模式需要更长的时间才能融入其中。(如果我记得正确的话,一位着名的C ++专家表示需要6个月到一年才能提高工作效率。)

一个好的调试器,特别是在执行时显示原始源代码和编译汇编代码的调试器,将帮助您更好地理解。

为了回应Evan Thinking in C++?,C ++是一种多范式语言。在C ++中思考主要是关于范式的思考。例如,libtiff完全基于函数指针,COM完全是关于OOP,只使用指针,vtable和引用计数。 MFC将很多东西包含在宏和表中。

在项目开始时,您有机会选择正确的范例。有时它受项目要求的限制,特别是如果它需要与外部环境接口。一旦项目开始,就很难切换。通常选择是有充分理由的。

了解范式的唯一方法是在使用它的项目中工作。