1. 程式人生 > >c++ 程式設計過程中遇到的問題積累

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);
//實際上同方法二,只是這裡的強制轉換的方式不一樣而已