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
問題四
關於靜態變數的宣告和定義。靜態成員屬於全域性變數,是所有例項化以後的物件所共享的,而成員的初始化可以想象成向系統申請記憶體儲存資料的過程,顯然這種共有物件不能在任何函式和區域性作用域中初始化。也不能在.h中初始化,必須在.cpp中初始化。
//.h class BaseServer { private: static int connfd; //declaration static variable and define in .cpp file static bool isConnected; } //.cpp
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);
//實際上同方法二,只是這裡的強制轉換的方式不一樣而已
問題十一
error: jump to case label
,解決辦法: 物件作用域的問題