2012-07-26 17 views
1

我的問題訪問派生類的信息如下:有問題的設計modifiying /使用基本對象

int main() 
{ 
    Base* derivedobject = new Derived1(); 
    derivedobject->GetProperties()-> ??? 

return 0; 
} 

//******************** 
// BaseClass.h 
//******************** 
struct PropertyStruct 
{ 
    int x; 
}; 

class Base 
{ 
public: 
    Base(); 
    ~Base(); 

    virtual PropertyStruct GetProperties() = 0; 

private: 
}; 

//******************** 
// DerivedClass1.h 
//******************** 
struct PropertyStruct 
{ 
    int y; 
}; 

class Derived1 : public Base 
{ 
public: 
    Derived1(); 
    ~Derived1(); 

    PropertyStruct GetProperties() { return myOwnDifferentProperties; }; 

private: 

}; 

//******************** 
// DerivedClass2.h 
//******************** 
struct PropertyStruct 
{ 
    float z; 
}; 

class Derived2 : public Base 
{ 
public: 
    Derived2(); 
    ~Derived2(); 

    PropertyStruct GetProperties() { return myOwnDifferentProperties }; 

private: 

}; 

如果我那樣做,我會得到一個錯誤,指出PropertyStruct是重新定義。如果我使用命名空間或重命名派生類中的結構,那麼我會得到一個錯誤,告訴我返回類型與Base定義的不同。 如果我將虛函數的返回類型定義爲它編譯的指針,雖然從主方法(在本例中)訪問函數「GetProperties」時的下一個問題是基類對象不知道變量結構中的變量是什麼類。

有沒有什麼辦法可以實現這一點? 我可以得到每個派生對象的不同屬性,但使用基類對象?

+0

您可以使用不同名稱建立兩個「PropertyStruct」之間的基礎派生關係。 – iammilind 2012-07-26 15:39:44

回答

0

由於模板函數不能是虛擬的,因此可以使用屬性的層次結構。這只是一種方式,沒有其他辦法。爲了獲得派生屬性的元素,你應該使用虛擬的getter函數。

struct BaseProp 
{ 
    virtual ~BaseProp() { } 
    virtual boost::any getProperty() const = 0; 
}; 

struct PropertyStruct : BaseProp 
{ 
    boost::any getProperty() const { return x; } 
private: 
    int x; 
}; 

struct PropertyStruct2 : BaseProp 
{ 
    boost::any getProperty() const { return y; } 
private: 
    float y; 
}; 

class Base 
{ 
public: 
    virtual std::shared_ptr<BaseProp> GetProperties() const = 0; 
    virtual ~Base() { } 
} 

class Derived 
{ 
public: 
    std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct(); } 
}; 

class Derived2 
{ 
public: 
    std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct2(); } 
}; 
+0

「別無他法」......真的嗎? – 2012-07-26 16:00:29

+0

@ Code-Guru沒有其他方法可以實現目標,那就是希望OP不需要派生。 – ForEveR 2012-07-26 16:42:21

0

您可以使用模板類來做到這一點:

struct PropertyStruct1 { 
    float f; 
}; 

struct PropertyStruct2 { 
    int i; 
}; 

template<class T> 
class A{ 
public: 
    T GetProperties() {return mProps;} 

private: 
    T mProps; 
}; 

int main (int argc, const char * argv[]) { 

    A<PropertyStruct1> a1; 
    int f = a1.GetProperties().f; 
    A<PropertyStruct2> a2; 
    int i = a2.GetProperties().i; 
    return 0; 
} 
2

正如其他人所說,有很多方法可以在這裏實現自己的目標,但最終你會發現自己就像下面寫代碼:

Base * object = ...; 

    if object is Derived1 then 
     get Property1 and do something with it 
    else if object is Derived2 then 
     get Property2 and do something with it 

這是面向對象編程中的一種反模式。您已經有一個類層次結構來表示各種派生類型之間的差異。不要從對象中提取數據並在外部處理數據,請考慮向基類添加虛擬函數,並讓派生類進行處理。

class Base 
{ 
public: 

    virtual void DoSomething() = 0; 
}; 

class Derived1 : Base 
{ 
public: 

    void DoSomething() 
    { 
     // use myOwnDifferentProperties as necessary 
    } 

private: 

    PropertyStruct myOwnDifferentProperties; 
}; 

如果它不適合把需要處理的派生類(即它是否會帶來惱人的責任),那麼你可能要考慮Visitor Pattern,以此來擴展層次的功能。