2017-04-03 64 views
1

我想創建一個基本的解析方法,它使用C++將vector <uint8_>作爲輸入。根據各個字節的實際值,此方法應返回一個表示此數據的結構。根據C++中的輸入,我可以使用相同的方法返回不同的對象嗎?

例如:

輸入1:{0x10, 0x02, 0x03}
輸入2 {0x20, 0x05, 0x02}

的第一個字節應該代表對象的類型與爲0x10 =立方體和爲0x20 =球體。
第二個字節取決於立方體的寬度或球體直徑的類型。
第三個字節是立方體的體積或球體的質量。

是否可以創建這需要基於該值這個矢量這兩種不同的結構中的一個內的輸入矢量,並返回一個方法:

struct cube 
{ 
    int width; 
    int volume; 
}; 

struct sphere 
{ 
    int diameter; 
    int mass; 
}; 
+0

4答案了。我想知道爲什麼「工會」還沒有被提及。我錯過了任何禁止使用工會的東西嗎?或者以不同的方式提問:您(OP)是否對使用聯合類型的解決方案感興趣? Answerers,什麼阻止你使用工會? – Yunnosch

+0

除了我不知道如何使用它們以外,沒有什麼能夠阻止我使用union類型;)如果有使用union的優雅解決方案,爲什麼不呢? – p0fi

+0

你是否需要返回類型的解析結果?我使用了一個通過指針的out參數(C++的方式是引用)。如果需要,我改變返回一個union-struct。在我的工作中(小型嵌入式系統),我期望處理結構參數並通過指針返回值,這就是爲什麼。但我可以適應你的需求。 – Yunnosch

回答

1

爲了從函數返回不同的類型,該類型必須相關(見下文)。另外,返回類型必須是指針或智能指針。

如果你想不相關類型的數據通信,返回給調用者,你有兩個選擇:

  • 採取基準參數對每個可能的一種struct,或
  • 採取接受的元素回調每種可能的種類。

第一種方法:

enum shape_t {Cube, Sphere}; 
shape_t parse(vector<uint8_t> data, cube &c, sphere& s) { 
    if (<data represents a cube>) { 
     c.width = ... 
     c.volume = ... 
     return Cube; 
    } else if (<data represents a sphere>) { 
     s.diameter = ... 
     s.mass = ... 
     return Sphere; 
    } else { 
     ... // Handle error 
    } 
} 

第二種方法:

struct parse_callback { 
    virtual void cube(const cube& c); 
    virtual void sphere(const sphere& s); 
}; 
... 
void parse(vector<uint8_t> data, parse_callback& cb) { 
    ... 
    if (<data represents a cube>) { 
     cube c; 
     c.width = ... 
     c.volume = ... 
     cb.cube(c); 
    } else if (<data represents a sphere>) { 
     sphere s; 
     s.diameter = ... 
     s.mass = ... 
     cb.sphere(s); 
    } 
} 

如果你不介意做你的類從一個共同的基礎繼承,您可以將智能指針返回到多態類型:

enum shape_kind {Cube, Sphere}; 

struct shape { 
    virtual ~shape() {} 
    virtual shape_kind kind() = 0; 
}; 

struct cube : public shape { 
    shape_kind kind() { return Cube; } 
}; 
struct sphere : public shape { 
    shape_kind kind() { return Sphere; } 
}; 

shared_ptr<shape> parse(const vector<uint8_t> data) { 
    if (<data represents a cube>) { 
     return shared_ptr<shape>(new cube); 
    } else { 
     return shared_ptr<shape>(new sphere); 
    } 
} 

Demo.

+2

第三種選擇:聲明一個基類,並返回一個std :: unique_ptr到該基地,然後調用者可以dynamic_cast到派生類中。 –

+0

@MartinBonner你似乎錯過了你正在評論的句子中的「無關」形容詞。 – dasblinkenlight

+2

或使用變體類型(例如'boost :: variant'或'std :: variant'。) – juanchopanza

0

空隙find_struct(矢量輸入,立方體& C1,球體& SP1) {

if (input[0] == 0x10) 
{ 
    c1.width = input[1]; 
    c1.volume = input[2]; 
} 
else if (input[0] == 0x20) 
{ 
    sp1.diameter = input[1]; 
    sp1.mass = input[2]; 
} 

}

INT主() {

vector <unsigned int> input1 = { 0x10, 0x02, 0x03 }; 
vector <unsigned int> input2 = { 0x20, 0x05, 0x02 }; 

cube c1; 
c1.volume = 0; 
c1.width = 0; 

sphere s1; 
s1.diameter = 0; 
s1.mass = 0; 

find_struct(input1,c1,s1); 

if (c1.volume != 0) 
{ 
    std::cout << "cube is returned" << std::endl; 
} 
if (s1.diameter != 0) 
{ 
    std::cout << "sphere is returned" << std::endl; 
} 

}

作爲一個備選,分配struct member 0作爲默認值。

然後,兩個立方體和球體的實例發送到功能find_struct, 這個函數返回修改後的C1 ANS SP1

檢查結構值不爲零!!!!

+0

謝謝,但這種解決方案並不是我正在尋找的,因爲這不適用於返回類型,而是參考參數。這將隨着越來越多的不同形狀而失控。 – p0fi

0

只是爲了保持它的簡單,仍然正確我認爲這是更好地保持由m.antkowicz建議的方法,並返回一個指向一個基本對象序,以提供一個多態行爲:

struct shape { 
    //... 
}; 

struct cube: shape { }; 
struct sphere: shape { }; 

// --- 

shape* foo(vector<uint8_> v) { 
    //... 
} 

通過這種方式,您的方法將能夠返回球體或立方體,甚至可以在未來輕鬆添加新形狀而不會發生重大更改。

當然,不是返回一個簡單的指針來形狀(shape*)它可能是一個智能指針std::shared_ptr<shape>,但現在我發現重要的是保持答案簡單,並專注於實際的解決方案。

0

這是基於聯盟和強大的C-氣息的建議,即小物體的方向。
(OP邀請與工會的建議,我想工會經常被引用的風險不是本次討論的目的問題。)
的主要設計descion是利用工會。

UPDATE:更改API和返回值。

我添加演示代碼,示出了使用可用於錯誤處理的變量的內部和用於檢測的那種形狀的信息的可能性。
我相信任何客戶端代碼(它處理分析器的結果)需要找出哪一種形狀的裏面。設計可以使用單一數據類型的API是不夠的。
我推測(不責怪缺乏信息的OP),如果客戶端代碼的不同部分可以被稱爲,每個隱含意識到那種接收形狀的
那麼就不會有需要找到一個數據設計可以將所有形狀放在一個類型中。

typedef enum tenCubeOrSphere_tag 
{ 
    nenInvalid = 0x0, 
    nenCube  = 0x10, 
    nenSphere = 0x20 
} tenCubeOrSphere; 

typedef struct tstCube_tag 
{ 
    tenCubeOrSphere enWhich; 
    // Note that this is the same for cube and for sphere 

    int width; 
    int volume; 
} tstCube; 

typedef struct tstSphere_tag 
{ 
    tenCubeOrSphere enWhich; 
    // Note that this is the same for cube and for sphere 

    int diameter; 
    int mass; 
} tstSphere; 

typedef union tunShape_tag 
{ 
    tstCube Cube; 
    tstSphere Sphere; 
    tstCube Unknown; 
    /* just for selfexplaining client code, 
     could also be tstSphere, same thing */ 
} tunShape; 

// That's it, below is just demonstrator code. 

tunShape parse(/* assume here an input parameter, 
       a reference to parseable vector */) 
{ tunShape Out; 

    { /* parsing happens here, 
     assume it finds a cube */ 
     Out.Cube.enWhich=nenCube; 
     Out.Cube.volume = /* let's say ... */ 5; 
     Out.Cube.width = /* hmm...  */ 125; 

     /* in case of sphere */ 
     Out.Sphere.enWhich =nenSphere; 
     Out.Sphere.diameter= /* let's say ... */ 30; 
     Out.Sphere.mass = /* hmm...  */ 14000; 
    } 

    return Out; 
} 

void client (void) 
{ tunShape unReceiver; 
    unReceiver = parse(/* iput vector */); 
    if  (unReceiver.Unknown.enWhich == nenInvalid) 
    {/* error handling */ 
    } else if (unReceiver.Unknown.enWhich == nenCube) 
    { std::cout << "It is a cube: " << unReceiver.Cube.volume << "," << unReceiver.Cube.width << std::endl; 
    } else /* obviously a sphere */ 
    { std::cout << "It is a sphere: " << unReceiver.Sphere.mass << "," << unReceiver.Sphere.diameter << std::endl; 
    } 
} 
+0

我在windows mingw上測試過,它只需要合適的包含並從main調用'client();'。 – Yunnosch

+0

我理解OP的評論以表明他理論上了解工會。我檢查了,stackoverflow沒有關於工會的文檔。 (如果我錯了,很高興看到鏈接。)如果需要某些解釋,請告訴我。 – Yunnosch

相關問題