2017-07-24 34 views
0

我有兩種相同方法的變體。我也有一個基類類型的實例,但我不知道它是一個實例的具體類。我現在想要根據對象的實際類型自動選擇適當的方法。這似乎是不可能的,唯一能解決的辦法是通過鑄造來檢查所有可能性。 雖然有一個更好的解決方案。基於類實例的自動方法選擇

這是我的小例子:

// Example program 
#include <iostream> 
#include <string> 
#include <memory> 

class A 
{ 
public:  
    virtual void bar() const = 0; 
}; 

class B : public A 
{ 
public: 
    void bar() const 
    { 
     std::cout << "B.bar()" << std::endl; 
    } 
}; 

class C : public A 
{ 
public:  
    void bar() const 
    { 
     std::cout << "C.bar()" << std::endl; 
    }  
}; 

class Z 
{ 
public: 
    Z(int variable) : m_variable(variable) {}; 

    void foo(std::shared_ptr<B> b) 
    { 
     std::cout << "Calling foo(B) method! " << m_variable << std::endl; 
     b->bar(); 
    } 

    void foo(std::shared_ptr<C> c) 
    { 
     std::cout << "Calling foo(C) method!" << m_variable << std::endl; 
     c->bar(); 
    } 
private: 
    int m_variable; 
}; 


int main() 
{ 
    std::shared_ptr<A> b(new B()); 

    Z z(42); 

    //z.foo(b); // This doesn't work 

    // But this does 
    std::shared_ptr<B> b_cast = std::dynamic_pointer_cast<B>(b); 
    if (b_cast.get()) 
    z.foo(b_cast); 
} 

http://cpp.sh/9fqne

目前,我不得不求助於dynamic_pointer_cast,但我覺得它有點醜,而不是非常維護。

我也不想將foo()的功能添加到類BC,因爲這些是許多其他類在其上運行的小型獨立數據結構。

非常感謝!

編輯:在原來的帖子我簡化了一下太多了。新的例子應該清除事情。

+3

您是否聽說過多態性?你可以讓他們成爲虛擬成員函數並獲得這種行爲。 – NathanOliver

+1

請注意,行'a = b;'導致切片。 (這裏沒有任何數據成員,但值得注意的是,這一行不會突然變成'B'。) – cdhowie

+1

閱讀關於多態性,繼承,接口,虛函數和指針等的指針。 – Ron

回答

1

將純虛函數foo()添加到您的基類並在隨後的派生類中重寫。然後讓你的整體功能foo()(其中有無關的成員函數具有相同的名稱)作爲參數接受以std::shared_ptr常量參考:

#include <iostream> 
#include <memory> 
class A{ 
public: 
    virtual void foo() = 0; 
}; 

class B : public A{ 
public: 
    void foo() override{ 
     std::cout << "Calling foo(B) method!" << std::endl; 
    } 
}; 

class C : public A{ 
public: 
    void foo() override{ 
     std::cout << "Calling foo(C) method!" << std::endl; 
    } 
}; 

void foo(const std::shared_ptr<A>& param){ 
    param->foo(); 
} 

int main(){ 
    std::shared_ptr<A> b = std::make_shared<B>(); 
    std::shared_ptr<A> c = std::make_shared<C>(); 
    foo(b); 
    foo(c); 
} 
+0

想象一下'foo'是另一個在'B'和'C'類型對象上運行的類的成員函數。由於我有很多這樣的類,我不想將所有的功能本身添加到'B'和'C'中。 'foo()'的結果也嚴重依賴於實現類的成員變量。 – Pfaeff

0

As BoBTFish pointed out,該visitor pattern是這個問題的一個潛在的解決方案:

// Example program 
#include <iostream> 
#include <string> 
#include <memory> 

class B; 
class C; 

class Visitor 
{ 
public: 
    virtual void visit(B* b) const = 0; 
    virtual void visit(C* b) const = 0; 
}; 

class A 
{ 
public:  
    virtual void bar() const = 0; 
    virtual void accept(const Visitor* visitor) = 0; 
}; 

class B : public A 
{ 
public: 
    void bar() const 
    { 
     std::cout << "B.bar()" << std::endl; 
    } 

    void accept(const Visitor* visitor) 
    { 
     visitor->visit(this); 
    } 
}; 

class C : public A 
{ 
public:  
    void bar() const 
    { 
     std::cout << "C.bar()" << std::endl; 
    } 

    void accept(const Visitor* visitor) 
    { 
     visitor->visit(this); 
    }  
}; 

class Z : public Visitor 
{ 
public: 
    Z(int variable) : m_variable(variable) {}; 

    void visit(B* b) const 
    { 
     std::cout << "Calling foo(B) method! " << m_variable << std::endl; 
     b->bar(); 
    } 

    void visit(C* c) const 
    { 
     std::cout << "Calling foo(C) method!" << m_variable << std::endl; 
     c->bar(); 
    } 
private: 
    int m_variable; 
}; 


int main() 
{ 
    std::shared_ptr<A> b(new B()); 

    Z z(42); 

    b->accept(&z); 
} 

http://cpp.sh/2vah5

非常感謝您!