2017-05-18 25 views
1

我有一個實現一個接口的對象集合,我想讓它有getters來獲取單獨的實現,只有在C++中。在Java中,我會這樣做:如何在不定義類型的情況下爲C++中的類型編寫getter?

interface IFooBar { } 
class Foo implements IFooBar { } 
class Bar implements IFooBar { } 

class Container extends HashSet<IFooBar> { 

    public Container() { } 
    public Container(Collection<? extends IFooBar> c) { super(c); } 

    Foo getFoo() { 
     return getFoos().iterator().next(); 
    } 

    Set<Foo> getFoos() { 
     HashSet<Foo> result = new HashSet<>(); 
     for(IFooBar item:this) if (item instanceof Foo) result.add((Foo) item); 
     return result; 
    } 

    Bar getBar() { /* ... same ... */ } 

    Set<Bar> getBars() { /* ... same ... */ } 
} 

現在我試着在C++中做同樣的事情。對於項目需求,我必須使用我的對象的shared_ptr<>。這是多遠我就來了:

class IFooBar { } 
class CFoo : IFooBar { } 
class CBar : IFooBar { } 

class CContainer { 
public: 
    CContainer(); 
    CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData); 

    const std::shared_ptr<CFoo> CFoo(); 
    std::vector<const std::shared_ptr<CFoo>> CFoos(); 
            /* ^^^^ : Function CContainer::CFoo is not a type name */ 
    const std::shared_ptr<CBar> CBar(); 
    std::vector<const std::shared_ptr<CBar>> CBars(); 

private: 
    std::vector<const std::shared_ptr<IObject>> m_cPrivData; 
}; 

顯然,這是不行的,我不能給吸它應有的名字(我認爲)。我收到了指示的錯誤。該函數似乎取消定義類型名稱。現在我不知道這將是我在C++中給出的Java示例的一個直觀可用的實現?或者,吸氣劑的推薦名稱是什麼?我瞭解到,在C++中,getter命名時不帶前導'get',函數名稱以大寫字母開頭。我想讓getter反映它返回的類類型。

也許我應該去完全其他的方式?我可以定義一個賦值構造函數,而不是函數CFoo(),如果是這樣,怎麼辦?我是否必須重載shared_ptr<>才能這樣做?如果是這樣,怎麼樣?像這樣的東西是我的想法:

class CSharedFooBarPointer : std::shared_pointer<IFooBar> { 
public: 
    shared_ptr<Foo> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer); 
    shared_ptr<Bar> operator=(std::vector<const std::shared_ptr<IFooBar>>& cContainer); 
} 

(也許是我想太多Java'ish這裏,但我很新的C++)。也許這種做法是不好的,因爲也許我不能在網上使用。或者我可以嗎?從上面的Java示例中,我希望能夠執行諸如container.getFoo().doSomethingFooSpecific();之類的操作。在C++中,我必須使用什麼語法?有沒有像((CFoo)cContainer).DoSomethingFooSpecific();?如果可能的話,我只需要使用一次變量就不需要分配變量。

+0

什麼是'IObject' ? –

+1

另外,C++並沒有真正擁有所有人都遵循的通用代碼約定,並且使用'Get'引導方法名稱是我見過的很多。 –

+2

名稱衝突可以通過添加'::'來解決。像'''const std :: shared_ptr <::CFoo> CFoo();''' – user5821508

回答

2

注意:此答案中的代碼未經測試,可能包含拼寫錯誤。

我瞭解到,在C++中,吸氣命名,而不會導致「得到」,和函數名開始大寫。

不是我所知。但正如Gill Bates所提到的那樣,C++沒有集中的樣式指南,所以只需選擇一種代碼樣式並堅持下去。我個人從來沒有看到用MFC和WINAPI以外的資本開始的函數 - 你可能會想到C#。同上C類前綴。

在任何情況下,名稱衝突可以與scope resolution operator ::來解決:

class CContainer { 
    // ... 
    const std::shared_ptr<CFoo> CFoo(); 
    std::vector<const std::shared_ptr<::CFoo>> CFoos(); 
    //  CFoo from the global scope ^^ 
    // ... 
}; 

獲得領先一步有關實現的功能:
要確定動態類型的對象在運行時,你需要dynamic_cast,或者你的情況是std::dynamic_pointer_cast輔助函數。

std::vector<const std::shared_ptr<::CFoo>> CContainer::CFoos() { 
    std::vector<const std::shared_ptr<::CFoo>> result; 

    for(auto const &objPtr : m_cPrivData) 
     if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr)) 
      result.push_back(std::move(fooPtr)); 

    return result; 
} 

然而,dynamic_cast需要該對象的類型是多態的,這意味着IFooBar需要具有至少一個虛擬成員函數。如果沒有足夠的功能存在,共同的選擇是使析構函數虛:效率

struct IFooBar { 
    virtual ~IFooBar() = default; 
}; 

注:
就像在Java中instanceofdynamic_cast是一個非常昂貴的操作。如果這個類的主要用例是過濾的CFoo S和CBars列表中,你可能想在構造函數中單獨的容器要做到這一點一次,並將其存儲:

class CContainer { 
public: 
    CContainer(std::vector<const std::shared_ptr<IFooBar>> cPrivData) { 
     for(auto const &objPtr : cPrivData) 
      if(auto fooPtr = std::dynamic_pointer_cast<::CFoo>(objPtr)) 
       _foos.push_back(std::move(fooPtr)); 
      else if(auto barPtr = std::dynamic_pointer_cast<::CBar>(objPtr)) 
       _bars.push_back(std::move(barPtr)); 
    } 

private: 
    std::vector<const std::shared_ptr<::CFoo>> _foos; 
    std::vector<const std::shared_ptr<::CBar>> _bars; 
}; 
相關問題