c++ 编程过程中遇到的问题积累

  • 问题一

    在使用继承时,遇到下面的问题

    error: ‘void BaseServer::StartServer(BaseServer*)’ is inaccessible
    void StartServer(BaseServer *m_bserver);

    即父类无法调入子类参数,原因竟是继承时忘记加public导致私有继承

  • 问题二

    在c中常常使用一个总头文件来定义全局变量,如果只在总头文件中声明,然后在其他头文件中include ,使用时会出现多次定义的错误。至少应该在.c中定义初始化,在头文件中使用extern。或者通过类的实例,类与类之间的关系来访问。

  • 问题三

    在linux下创建线程时,创建线程的函数与c++的语法冲突(c++相对于c语法更加严格一些)

    pthread_create(&pthread_id, NULL, ServerThread, NULL)
    (error: invalid conversion from ‘void*’ to ‘void* ()(void)’)

    解决办法,将线程函数设置为c,不在类中定义。即ServerThread设置为c函数,声明时加

    
    #ifdef __cplusplus
    
    extern "C" {
    
    #endif
    
    
    static void *ServerThread(void *);
    
    
    #ifdef __cplusplus
    
    }
    
    #endif
    
    
    //(void *)也必须添加
  • 问题四

    关于静态变量的声明和定义。静态成员属于全局变量,是所有实例化以后的对象所共享的,而成员的初始化可以想象成向系统申请内存存储数据的过程,显然这种共有对象不能在任何函数和局部作用域中初始化。也不能在.h中初始化,必须在.cpp中初始化。

    //.h
    class BaseServer
    {
    private:
      static int connfd; //declaration static variable and define in .cpp file
      static bool isConnected;
    }
    //.cpp
    int BaseServer::connfd = 0;
    bool BaseServer::isConnected = 0;
  • qt中浮点数转换为字符串时,如果使用QString("%1").arg(data)该种方法,得出的字符串位数很少,影响显示数值的精度。另外一种方法是

    QString QString::number(double n, char format = ‘g’, int precision = 6) [static]
    Returns a string equivalent of the number n, formatted according to the specified format and precision. See Argument Formats for details.

    Unlike QLocale::toString(), this function does not honor the user’s locale settings.

    QString::number(data,'g',10);//10代表10个字符
  • 问题五

    定义了类指针而不new,坑了一天!

  • 问题六

    assert 函数: assert 是个宏, 这个宏检查传给它的表达式是否非零, 如果不是非零值, 就会发出一条出错信息并调用 abort. assert 只是在没定义标准宏NDEBUG 的时候, 即在调试状态下才这么做。在产品发布状态下, 即定义了NDEBUG 的时候, assert 什么也不做, 相当于一条空语句。所以你只能在调试时才能检查断言

  • 问题七

    回调函数: 系统每次调用该函数时,如果函数中定义有变量并赋有初值,那么每次调用这些变量,其值都将被重置。这点务必重视。使用static即可解决。

    静态局部变量使用说明:

    • 在静态存储区内分配存储单元,程序整个运行期间不释放
    • 在编译时赋初值,只赋初值一次。每次保留上次函数调用结束时的值
    • 若不赋初值则编译自动赋值为0(数值型变量)或空字符(字符型变量)
    • 在其他函数中不可见
    • 用完该值后尽快复位,以免引起不必要的逻辑错误
  • 问题八

    隐式转换: 务必注意

    
    #include <stdio.h>
    
    
    void test(float a)
    {
      printf("%f\n",a);
    }
    
    int main()
    {
      int i=10;
      test((float)i/100);//0.100000
      test(i/100);//0.000000
        test(i/100.0f);//0.100000
      return 0;
    }
    //两次test的值不一样!!!!!
    //printf("%.nf",&f);//n代表显示浮点数时,小数点后显示几位
  • 问题九

    使用scanf读取文本中固定格式数据

FILE *fp = fopen("InitPos","r");
fscanf(fp,"x:%f,y:%f,yaw:%f",&fCurX,&fCurY,&fCurYaw);//这里的变量不能是double型
  • 问题十

    cannot convert from type void*(classname::) () to type void*(*)(void*)

    解决方法:(参考链接)

    • 方法一:将传入pthread_create的函数定义为static
    void *Test::Func(void *)//static
    {
      std::cout << "hello" << std::endl;
    }
    
    void Test::CreateThread()
    {
      pthread_t id;
      int err = pthread_create(&id,NULL,Func,NULL);
      if(err != 0)
          std::cout << "can't create thread" << std::endl;
    }
    • 方法二:往往Func函数有很多类的成员,因此并不想让Func函数定义为static(定义为static便无法访问类成员)

    If you want to use pthreads, then you’ll need a static or non-member function for the entry point. You can pass a pointer to your object to this function, using it as a trampoline into the non-static member function:

    class Test
    {
    public:
      Test();
      void* Func(void* arg);
      void CreateThread();
      static void* helpFunc(void* self)
      {
          return static_cast<Test*>(self)->Func(self);
      }
    };
    
    void Test::CreateThread()
    {
      pthread_t id;
      int err = pthread_create(&id,NULL,helpFunc,this);
      if(err != 0)
          std::cout << "can't create thread" << std::endl;
    }

    static_cast < type-id > ( expression )该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

    它主要有如下几种用法:

    • 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
    • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
    • 把void指针转换成目标类型的指针(不安全!!)
    • 把任何类型的表达式转换成void类型。

    注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。

    • 方法三:
void RecvCommand();
static void RecvProc(int nArgv)
{
    ((CRead*)nArgv)->RecvCommand();
        return ;
}
m_pthread->CreateThread(CRead::RecvProc,this);
//实际上同方法二,只是这里的强制转换的方式不一样而已

猜你喜欢

转载自blog.csdn.net/robothj/article/details/80304081
今日推荐