<<C++ 沉思录>> 中文人民邮电出版 勘误

<<C++ 沉思录>> 中文人民邮电出版 勘误

这本中文版里面有各种坑爹的小错误. 比方说变量名的大小写, 同一个变量, 出现了大小写不一致, 等等问题都有.

然后今天感觉遇到了个语法问题. 关于继承权限的问题.

书中第八章的demo里面, 关于class Expr_node.

使用了protected关键字. 但是这里Expr_node是基类, 继承就会出现问题.

具体的代码如下:

class Expr_node
{
    friend ostream& operator << (ostream&, const Expr_node&);
    friend class Expr;

    int use;// @use is a counter to avoid copying objects.

    //protected:
    public:
        Expr_node(): use(1) { }
        virtual void print(ostream&) const = 0;
        virtual ~Expr_node() { }
        virtual int eval() const = 0;
};

这里用protected就会error.

protected本来就是为了明确不发生继承的区域. 这里这堆虚函数是要发生继承的.就是为了占坑了让子类去实现.

这里应该使用public, 而不是 protected.

由于可能在"挑战权威" , 所以把问题抛出来, 希望有心人能一起讨论.

下面是完整的代码. 可供测试

/*
    Programmer  :   EOF
    Date        :   2015.05.19
    File        :   8.4.cpp
    E-mail      :   [email protected]

 */
#include <iostream>
#include <string>

using namespace std;

/*
   This @Expr_node is the base-class.
 */
class Expr_node
{
    friend ostream& operator << (ostream&, const Expr_node&);
    friend class Expr;

    int use;// @use is a counter to avoid copying objects.

    protected:
    //public:
        Expr_node(): use(1) { }
        virtual void print(ostream&) const = 0;
        virtual ~Expr_node() { }
        virtual int eval() const = 0;
};

class Expr
{
    friend ostream& operator<<(ostream&, const Expr&);
    Expr_node* p;

    public:
        Expr():p(NULL){}
        Expr(int);
        Expr(const string&, Expr);
        Expr(const string&, Expr, Expr);
        Expr(const Expr& t) { p = t.p; ++p->use; };

        Expr& operator=(const Expr&);

        ~Expr() { if(--p->use == 0) delete p;}

        int eval() const {return p->eval();}
};

ostream&
operator<<(ostream& o, const Expr_node& e)
{
    e.print(o);
    return o;
}

Expr&
Expr::operator=(const Expr& rhs)
{
    rhs.p->use++;
    if(--p->use == 0)
    {
        delete p;
    }

    p = rhs.p;
    return *this;
}

ostream&
operator<<(ostream& o, const Expr& t)
{
    t.p->print(o);
    return o;
}

class Int_node: public Expr_node
{
    friend class Expr;

    int n;

    Int_node(int k): n(k) { }
    void print(ostream& o) const { o << n;}
    int eval() const { return n;}
};

class Unary_node: public Expr_node
{
    friend class Expr;
    string op;
    Expr opnd;
    Unary_node(const string& a, Expr b):
        op(a), opnd(b) { }

    void print(ostream& o) const
    {
        o << "(" << op << opnd << ")";
    }

    int eval() const
    {
        if(op == "-")
        {
            return -opnd.eval();
        }

        throw "error, bad op" + op + "int UnaryNode";
    }
};

class Binary_node: public Expr_node
{
    friend class Expr;
    string op;

    Expr left;
    Expr right;

    Binary_node(const string& a, Expr b, Expr c):
        op(a), left(b), right(c) { }

    void print(ostream& o) const
    {
        o << "(" << left << op << right << ")";
    }

    int eval() const
    {
        int op1 = left.eval();
        int op2 = right.eval();

        if(op == "-") return op1 - op2;
        if(op == "+") return op1 + op2;
        if(op == "*") return op1 * op2;
        if(op == "/") return op1 / op2;

        if(op == "/" && op2 != 0) return op1/ op2;

        throw "error, bad op" + op + "int BinaryNode";
    }
};

Expr::Expr(int n)
{
    p = new Int_node(n);
}

Expr::Expr(const string& op, Expr t)
{
    p = new Unary_node(op, t);
}

Expr::Expr(const string& op, Expr left, Expr right)
{
    p = new Binary_node(op, left, right);
}

int main()
{
    Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4));
    cout << t << " = " << t.eval() << endl;
    t = Expr("*", t, t);
    cout << t << " = " << t.eval() << endl;

    return 0;
}
时间: 2024-10-11 04:20:14

<<C++ 沉思录>> 中文人民邮电出版 勘误的相关文章

设计模式沉思录——互动出版网

这篇是计算机类的优质预售推荐>>>><设计模式沉思录> GoF成员.<设计模式>一书作者之一John M. Vlissides为你揭开模式设计的神秘面纱 内容简介 本书在GoF的<设计模式>一书的基础上进行了拓展,运用其中的概念,介绍了一些技巧,帮助读者决定在不同的情况下应该使用哪些模式,以及不应该使用哪些模式.本书不仅对已有的一些模式提出新的见解,还让读者见证开发新模式的整个过程. 本书适合使用设计模式的软件开发人员阅读. 作译者 作者介绍 J

重现仙剑奇侠的梦境(人民邮电报专栏《乐游记》之35)

别忘了游戏的编剧不是什么文学大家,即使是有情节的游戏也往往流于俗套,玩家在别人设定的剧情中难免产生遗憾.如何补完?自己重新编织新的剧情,用文字来演绎在游戏中没有实现的"零件",就成了同人小说.游戏文学 文/张书乐 刊载于11月28日<人民邮电报>应用版乐游记专栏 在电影院花两个半小时看一部电影值不值得?对于<星际穿越>来说,这是个伪命题.从这部备受期待的电影中,我看出了向库布里克的<太空漫游2001>致敬的诸多内容,还有对我们儿时的科学幻想进行视觉演

网络文学咋来的?(人民邮电报专栏《乐游记》之33)

在文学网站上最受欢迎的,还是标注着某个游戏名称的衍生同人作品.那些作品一头连着真正好玩的游戏,自然就带来了一大群读者. 刊载于11月14日<人民邮电报>应用版乐游记专栏 张书乐 不少朋友都觉得我在读书的选择上比较"奇葩".这不怪朋友们,因为我买书的第一原则是尽可能读死人的书.这样讲可能让人有点害怕,但却是大实话.现在的图书太多了,一位出版社的朋友告诉我,国内一年出版的图书就有几十万部.对于我来说,选择"大浪淘沙"之后留传下来的书,可以减少选书的难度,而且

从“水下八关”的传说说起(人民邮电报专栏《乐游记》之17)

越不容易开启的隐藏关卡,越容易成为剧情的特殊分支,直接影响到游戏的结局,而这激发了玩家高亢的游戏热情,同时让游戏经久不衰. 文/张书乐 二周目.隐藏角色.隐藏关卡等等探宝式的游戏玩法,让游戏具有了更强的续航力.任何事物都有一个起源,而在我看来,这一切都源于与<魂斗罗>有关的"水下八关"传说,这个传说和中国游戏玩家关系很大. 在没有社交网络的时代,<魂斗罗>游戏非常流行.而在游戏第六关有一个bug(程序漏洞),会使敌兵的图形显示不正常,变成类似青蛙嘴的模样.在中国

C++沉思录之二——虚函数使用的时机

虚函数使用的时机 为什么虚函数不总是适用? 1. 虚函数有事会带来很大的消耗: 2. 虚函数不总是提供所需的行为: 3. 当我们不考虑继承当前类时,不必使用虚函数. 必须使用虚函数的情况: 1. 当你想删除一个表面上指向基类对象,实际却是指向派生类对象的指针,就需要虚析构函数. C++沉思录之二--虚函数使用的时机,布布扣,bubuko.com

个性化的亲切——《沉思录》引发的感悟

记得初中那阵子,曾经追过明星,甚至美的标准也变成了他——恨不得所有的明星都是长的和他一样,唱的和他一样.除了他的歌,我几乎欣赏不了其他人的歌. 还记得差不多在那个年纪,曾经幻想过世界“大统”——我认为“大统”是达到“大同”,消弭纷争的有效方式.惭愧,后来知道希特勒也是这么想的.此乃后话,不提. 也几乎是那个时候,我不愿再做“出头鸟”,我相信“人多力量大”,我总愿意融在身边的“圈子”,不想显得自己不合群. 个性化,在我们的应试教育体制中从来都没有得到特别的提倡,如果没有良师益友的及时提点,一定会让

GAME不会OVER(人民邮电报专栏《乐游记》之16)

许多单机游戏在上个世纪的最佳"活法"--让玩家不断地玩下去,而不会因为"GAME OVER"而离开.在每一个游戏研发者心中,GAME不会OVER的游戏,才是好游戏. 张书乐 记得网上有个流传已久的笑话,大意是说某个有官瘾而无官运的男子,将自家的所有房间均挂上政府机关的牌子,如书房为"文化厅".客厅为"广电总局".卧室为"计生委",连厕所也堂而皇之地挂上了"卫生部"的牌子--原本以为这只是

玩好一款游戏很重要(人民邮电报专栏《乐游记》之15)

游戏的最大妙用就在于,它或许能指导我们的现实生活,又或者能帮我们获得更好的生活,或许你不相信,但文章中的故事,确确实实发生过,而且是那么的正常. 文/张书乐 年龄大了以后,我发现外语真的很管用.某日中午,我在午睡,朋友在微信上给我发了个单词"relex".被弄醒的我,半天没有回过神来,毕竟快十年没有和"英格里希"(Engliash)打过什么实质性的交道了.向百度.谷歌求助后,我也没得出什么结果,琢磨了将近一中午,后来猛然醒悟,可能是拼写有误的"relax&

迷你MVVM框架 avalonjs 沉思录 第1节 土耳其开局

#cnblogs_post_body p{ text-indent:2em; margin-top: 1em; } 正如一切传说的开端那样,有一远古巨神开天辟地,然后就是其他半神喧宾夺主.我们对最巨贡献与创建力的远古巨神懵懂不知,却对巫师们的话语津津乐道.这同样也是我们前端的现实. MVVM是来自.NET,另一个遥远的界域.前端,相对于后端,怎么看都是蛮夷之地.JS这个肩负着前端一切交互工作的语言,竟然被视为恶魔,屡屡被屏蔽禁用.些微可用的脚本,变量与函数没有组织地野蛮生长着,直到JAVA的传教