我正在將應用程序從Windows移植到Linux。 一個組件從文件讀取結構化數據。C++通過類範圍訪問實例的成員
樣品輸入: #10 = CLOSED_POCKET(2.0,地毯);
對於每個可能的實體,都會從類型定義中生成相應的C++類。 工廠根據實體的名稱(如CLOSED_POCKET)創建相應的對象。之後,這些屬性被一個接一個地讀取。因此,我們希望通過當前屬性的索引來分配C++類的成員。
代碼正常與Visual Studio 2010中的Windows編譯我移植的代碼到Linux 10.04(清醒山貓)和Eclipse CDT的靛藍與GCC 4.4.6編譯成功了。
Linux上的問題: 當我訪問屬性的方法時,調試器有時會跳轉到錯誤的函數(當子類的函數應該被調用時,函數偏移量不正確)會導致分段錯誤。
我做了一個最小的例子,這也導致了分段錯誤(見下文)。
我現在的問題是:當Windows能夠成功運行它,我有什麼做的,用GCC在Linux下運行呢?
我知道根據C++標準,Downcasting虛擬繼承類是非法的(請參閱Downcast in a diamond hierarchy ),但也許存在另一種通過類作用域訪問實例成員的解決方案。 虛擬繼承是必需的,因爲從ISO標準給出的實體結構。
我還約因子評分提供每個實例的訪問陣列(MemberPtrArray),但與約80,000實體閱讀,在類範圍的訪問會更好。
/*
* MemberPointerTest.h
*/
#ifndef MAINTEST_H_
#define MAINTEST_H_
#include <string>
class BaseAttribute{
public:
virtual void SetReal(double value);
virtual void SetSelectName(std::string selectName);
};
class RealAttribute : public BaseAttribute{
public:
double value;
virtual void SetReal(double value);
};
class SelectAttribute: public BaseAttribute{
public:
std::string selectName;
virtual void SetSelectName(std::string selectName);
};
class BaseEntity{
public:
BaseAttribute id;
virtual ~BaseEntity(){}
};
class PocketEntity : virtual public BaseEntity{
public:
RealAttribute depth;
};
class ClosedPocketEntity : virtual public PocketEntity{
public:
SelectAttribute surfaceType;
static BaseAttribute ClosedPocketEntity::* memberPtrArray[3];
BaseAttribute* GetMember(unsigned int index);
};
#endif
/*
* MemberPointerTest.cpp
*/
#include "MemberPointerTest.h"
void BaseAttribute::SetReal(double value){
}
void BaseAttribute::SetSelectName(std::string selectName){
}
void RealAttribute::SetReal(double value){
this->value = value;
}
void SelectAttribute::SetSelectName(std::string selectName){
this->selectName = selectName;
}
BaseAttribute ClosedPocketEntity::* ClosedPocketEntity::memberPtrArray[] = {
(BaseAttribute ClosedPocketEntity::*) &PocketEntity::depth,
(BaseAttribute ClosedPocketEntity::*) &ClosedPocketEntity::surfaceType
};
/* Tried the following alternatives:
* &PocketEntity::depth, // cannot convert ‘RealAttribute PocketEntity::*’ to ‘BaseAttribute ClosedPocketEntity::*’ in initialization
* (RealAttribute ClosedPocketEntity::*) &ClosedPocketEntity::depth, // invalid conversion from ‘RealAttribute ClosedPocketEntity::*’ to ‘BaseAttribute ClosedPocketEntity::*’
*/
BaseAttribute* ClosedPocketEntity::GetMember(unsigned int index){
return &(this->*memberPtrArray[index]);
}
int main(){
ClosedPocketEntity cpEntity;
// Case 1: Calls SetReal of BaseAttribute
BaseAttribute* depthPtr = cpEntity.GetMember(0);
depthPtr->SetReal(3.0);
// Case 2: Produces Segmentation fault
RealAttribute* depthPtr2 = dynamic_cast<RealAttribute*>(cpEntity.GetMember(0));
depthPtr2->SetReal(2.0); // SIGSEGV
return 0;
}
哦,我......... – 2012-03-06 15:16:12