有问题的设计使用基础对象修改/访问派生类的信息

时间:2012-07-26 15:32:53

标签: c++ inheritance polymorphism derived

我的问题如下:

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定义的不同。 如果我将虚函数返回类型定义为它编译的指针,虽然从main方法(在本例中)访问函数“GetProperties”时的下一个问题,基础对象不知道派生类的结构中有哪些变量

有什么方法可以实现这个吗? 我可以获得每个派生对象的不同属性,但使用基类对象?

3 个答案:

答案 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视为扩展层次结构功能的一种方法。

答案 1 :(得分: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(); }
};

答案 2 :(得分: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;
}