を経由して、インスタンスのメンバーにアクセスします。 1つのコンポーネントがファイルから構造化データを読み取ります。C++、私はWindowsからLinuxへアプリケーションを移植していたクラスのスコープ
サンプル入力: #10 = CLOSED_POCKET(2.0、カーペット)。対応するC++クラスは型定義から生成される全ての可能なエンティティの
。 ファクトリは、エンティティの名前(CLOSED_POCKETなど)に応じて、対応するオブジェクトを作成します。その後、属性は次々に読み取られます。したがって、現在の属性のインデックスを使用してC++クラスのメンバーを割り当てたいと考えています。
コードはVisual Studio 2010でコンパイルされたWindows上で正しく動作します。コードをLinux 10.04(Lucid Lynx)に移植し、Eclipse CDT Indigoでgcc 4.4.6を使用して正常にコンパイルしました。
Linuxの問題: 属性のメソッドにアクセスすると、デバッガが間違った関数にジャンプすることがあります(サブクラスの関数を呼び出すときに関数のオフセットが正しくない場合)。
Iは、(下記参照)セグメンテーション障害をもたらす最小の例を作りました。
私の質問は今です:Windowsを正常に実行するには、LinuxでGCCを実行するには何が必要ですか?
私は、仮想継承したクラスをダウンキャストすると、C++標準(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;
}
ああ、私......... –