C++遇到的bug总结

1. error: passing ‘const xxx’ as ‘this’ argument discards qualifiers [-fpermissive]

        分析:const修饰实例对象调用了非const修饰的成员方法。

        解决方案:将对象变为非const的,或者使用const修饰成员方法

2. error: 'xxx' does not name a type

        在复现《C++ Primer》书中的Text Queries源码时,由于多个头文件需要相互包含,就出现上上述的代码。其原因是如果需要声明或者定义一个类的指针的时候,就必须在使用之前,就已经声明或者定义了这个类。否则,编译器就找不到这个类。

(1)在query_base.hpp文件中

#ifndef __QUERY_BASE_HPP__
#define __QUERY_BASE_HPP__
#include "query.hpp"
#include "textQuery.hpp"
#include "queryResult.hpp"
#include <string>


class Query;
class Query_Base{
    friend class Query;
protected:
    using line_no = TextQuery::data_type;
    virtual ~Query_Base() = default;
private:
    virtual QueryResult eval(const TextQuery&) const = 0;
    virtual std::string rep() const = 0;
};

#endif //__QUERY_BASE_HPP__

         在query_base.hpp文件中,Query_Base类需要以Query为友元类。

(2)在query.hpp文件中

#ifndef __QUERY_HPP__
#define __QUERY_HPP__
#include "textQuery.hpp"
#include "queryResult.hpp"
#include "query_base.hpp"
#include <iostream>
#include <memory>
#include <string>

class Query{
    friend Query operator~(const Query&);
    // friend Query operator&(const Query&, const Query&);
    // friend Query operator|(const Query&, const Query&);
    friend std::ostream operator<<(std::ostream, const Query&);
public:
    Query(const std::string&);
    QueryResult eval(const TextQuery& t) const{
        return q->eval(t);
    }
    std::string rep() const{
        return q->rep();
    }
    std::shared_ptr<Query_Base> q;
    Query(std::shared_ptr<Query_Base> query):q(query){};    

};

#endif //__QUERY_HPP__

        如下图所示会出现这类错误:

        这是因为在query.hpp中,Query类中还使用到了Query_Base类作为成员变量。这种相互include的方式,会使得编译器无法正确的找到两个类的定义。因此,需要使用声明的方式代替include方式,从而打破这个死循环。

        正确的修改方法是,由于Query中需要使用Query_Base的成员方法,因此可以保留include的方式,而在query_base.hpp头文件中注释掉include方式,改用声明的方式。所以,修改后的query_base.hpp文件如下:

(3)补充一下

        上述Query_Base类实际上只是一个接口,如果其继承类需要使用到Query的具体方法,该类的实现不应该在query_base.hpp中实现,而应该写在一个新的hpp文件中,并include "query.hpp"头文件。

        下面就是在子类中使用了Query实例对象的成员方法,从而导致出现了问题。

         争取的方法是将NotQuery放到一个新的头文件中:

         这样的话,not_query.hpp中只是单向的包含Query类,而Query中并没有include "not_query.hpp"。

        所以强烈建议将接口及其子类,或者基类及其子类都分别写在不同的头文件中

        综上所述,如果是需要在一个A类中简单的声明另一个B类,则使用class B;的形式进行声明就行;如果需要使用B类的成员,则需要include B的头文件。否则,在A中就无法正常的使用B。

  参考链接:前置声明与C++头文件互相包含导致的error: 'xxx' does not name a type问题_imred的博客-CSDN博客

 3. error.undefined reference to `operator~

        分析:operator~声明了两次,但是只定义了一次。可以看一下下面的代码:

namespace A {
   struct B {
      friend std::ostream& operator<<( std::ostream&, B const & ); // [1]
   };
}
std::ostream& operator<<( std::ostream& o, A::B const & ) {        // [2]
   return o;
}

         其中【1】声明了operator<<运算符,但是在【2】中声明并且定义了operator<<运算符。

        解决方案:

namespace A {
   struct B  { friend std::ostream& operator<<( std::ostream&, B const & ); };
   std::ostream& operator<<( std::ostream&, B const & );
}
std::ostream& A::operator<<( std::ostream& o, B const & ) {
   return o;
}

        参考链接:c++ - undefined reference to operator<< - Stack Overflow

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值