首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

《C++沉思录》第八章 编译通不过解决方法

2013-12-11 
《C++沉思录》第八章 编译通不过expr.h#ifndef EXPR_H#define EXPR_H#include node.h#include string#in

《C++沉思录》第八章 编译通不过
expr.h


#ifndef EXPR_H
#define EXPR_H
#include "node.h"
#include <string>
#include <iostream>
using namespace std;

//句柄类
class Expr
{
    friend ostream& operator<<(ostream& o, const Expr& e);
    Expr_node* p;

public:
    Expr(int data);
    Expr(const string& op, Expr e);
    Expr(const string& op, Expr a, Expr b);
    Expr(const Expr& e);
    Expr& operator=(const Expr& rhs);
    ~Expr();
};

#endif // EXPR_H


expr.cpp

#include "expr.h"

Expr::Expr(int data)
{
    p = new Int_node(data);
}
Expr::Expr(const string& op, Expr e)
{
    p = new Unary_node(op, e);
}
Expr::Expr(const string& op, Expr a, Expr b)
{
    p = new Binary_node(op, a, b);
}
Expr::Expr(const Expr& e)
{
    p = e.p;
    ++p->use;
}
Expr::~Expr()
{
    if (--p->use == 0)
    {
        delete p;
    }
}
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& e)
{
    e.p->print(o);
    return o;
}



node.h

#ifndef NODE_H
#define NODE_H
#include "expr.h"
#include <string>
#include <iostream>
using namespace std;

class Expr_node
{
public:
    Expr_node(): use(1) {}
    virtual ~Expr_node() {}
    virtual void print(ostream&) const = 0;

private:
    int use;
    friend class Expr;
    friend ostream& operator <<(ostream& o, const Expr_node& e);
};

class Int_node: public Expr_node
{
public:
    Int_node(int k): n(k) {}
private:
    friend class Expr;
    int n;
    void print(ostream& o) const { o << n; }
};

class Unary_node: public Expr_node
{
public:
    Unary_node(const string& a, Expr b)
        : op(a), opend(b) {}
private:
    string op;
    Expr opend;
    void print(ostream& o) const
    {
        o << "(" << op << opend << ")";
    }
    friend class Expr;
};

class Binary_node: public Expr_node
{
public:
    Binary_node(const string a, Expr b, Expr c)
        :op(a), left(b), right(c) {}
private:
    void print(ostream& o) const
    {
        o << "(" << left << op << right << ")";
    }

    friend class Expr;
    string op;
    Expr left;
    Expr right;
}

#endif // NODE_H



main.cpp

#include <iostream>
#include "Expr.h"
#include <string>
using namespace std;

int main()
{
    Expr t = Expr("*", Expr("1", 5), Expr("+", 3, 4));
    cout << t;
    t = Expr("*", t, t);
    cout << t <<endl;
    return 0;
}



[解决办法]

引用:
就是要互相调用。。

就算要互相调用,先理清楚顺序也是必须的,头文件最好不要互相调用,不然会很麻烦。你这样调整下就好了。
#ifndef EXPR_H
#define EXPR_H
#include <string>
#include <iostream>

class Expr_node
{
public:
Expr_node(): use(1) {}
virtual ~Expr_node() {}
virtual void print(std::ostream&) const = 0;

private:
int use;
friend class Expr;
friend std::ostream& operator <<(std::ostream& o, const Expr_node& e);
};


//句柄类
class Expr
{
friend std::ostream& operator<<(std::ostream& o, const Expr& e);
Expr_node* p;

public:
Expr(int data);
Expr(const std::string& op, Expr e);
Expr(const std::string& op, Expr a, Expr b);
Expr(const Expr& e);
Expr& operator=(const Expr& rhs);
~Expr();
};

#endif // EXPR_H

#ifndef NODE_H
#define NODE_H
#include "expr.h"
#include <string>
#include <iostream>

class Int_node: public Expr_node
{
public:
Int_node(int k): n(k) {}
private:
friend class Expr;
int n;
void print(std::ostream& o) const { o << n; }
};

class Unary_node: public Expr_node
{
public:
Unary_node(const std::string& a, Expr b)
: op(a), opend(b) {}
private:
std::string op;
Expr opend;
void print(std::ostream& o) const
{
o << "(" << op << opend << ")";
}
friend class Expr;
};

class Binary_node: public Expr_node
{
public:
Binary_node(const std::string a, Expr b, Expr c)
:op(a), left(b), right(c) {}
private:
void print(std::ostream& o) const
{
o << "(" << left << op << right << ")";
}

friend class Expr;
std::string op;
Expr left;
Expr right;
};

#endif // NODE_H

[解决办法]
用前置声明试试
[解决办法]
引用:
就是要互相调用。。

你这种用法是错误的,Expr 和 Expr_node是互为不完全类型.
不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数. 
Expr opend; 你这样是直接定义该类型的对象了,编译器得生成代码,调用Expr的默认构造函数. 可是对于Expr_node类来说,这个Expr还是个不完全类型,编译器无法生成代码....,建议改成引用或指针

[解决办法]
文件相互包含或循环包含,是允许,但是会导致编译时间过长,甚至会崩溃。

此时解决的方式是预先声明。  

expr.h  声明将要使用的node.h中的类名称,
class  Expr_node ; //先声明Expr_node是一个类,编译器遇到名称Expr_node时,就会将其识别为一个类,但类的定义却暂时无须理会。
class Expr
{
  //这里就可以使用Expr_node*定义变量或参数了。
};

node.h  声明将要使用的expr.h中的类名称.

这样编译器就不会陷入循环编译的头文件怪圈中。就是为了避免“循环编译的头文件”有时得调整头文件的次序,为了加快编译速度,还得使用预编译头文件。

不存两个类相互包含的情况(即A中有B,B中有A的情况,这通不过编译)。这情况要通过指针来解决。



[解决办法]
Expr 和 Expr_node是互为不完全类型.
对不完全类型做个总结.
      不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用(但无法通过该指针或引用访问其成员变量或成员函数)或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数. 
那不完全类型只能用于定义指向该类型的指针及引用,其实道理很简单,遇到指针或引用,只要根本四个字节的空间就行了,不必知道该类型的细节
[解决办法]
在expr.h文件中加入class Expr_node;作为前置声明。class Expr_node;要放到 class Expr 的前面
然后在expr.cpp文件中#include"node.h"
[解决办法]
引用:
文件相互包含或循环包含,是允许,但是会导致编译时间过长,甚至会崩溃。

此时解决的方式是预先声明。  

expr.h  声明将要使用的node.h中的类名称,
class  Expr_node ; //先声明Expr_node是一个类,编译器遇到名称Expr_node时,就会将其识别为一个类,但类的定义却暂时无须理会。
class Expr
{
  //这里就可以使用Expr_node*定义变量或参数了。
};

node.h  声明将要使用的expr.h中的类名称.

这样编译器就不会陷入循环编译的头文件怪圈中。就是为了避免“循环编译的头文件”有时得调整头文件的次序,为了加快编译速度,还得使用预编译头文件。

不存两个类相互包含的情况(即A中有B,B中有A的情况,这通不过编译)。这情况要通过指针来解决。

BD

热点排行