在c ++中存储/返回继承类的最佳方法

时间:2013-01-25 14:10:03

标签: c++ pointers inheritance wrapper

我正在为一些自动生成的类编写一个包装器,以提供更好的接口。我写了一个简化的例子来证明这个问题。

我有一个A类,它有一个指向X类对象的指针,然后我有B类(继承A),它有一个指向Y类对象的指针(继承X)。

这一切都很好,除了我不确定将指针存储到X和Y的最佳方法是什么。我需要能够操纵A类和B类对象的集合,就像它们都是A一样(带有指向X的指针就是我需要的所有内容),这可以在下面的示例中正常工作。

我的实际问题是如何最好地处理需要操纵Y类对象而不是X类的B类情况。我确信有一些非常明显的东西我可以在这里使用。每次使用它时必须重复转换此变量并为继承我创建的A的每个类定义一个具有不同名称(例如getY)的方法,这感觉很笨拙。可能有很多方法,比如doStuff,所有这些方法都必须调用getY。

class X {
private:
    int i;
public:
    X(int i) : i(i) {}
    int getI() {
        return i;
    }
};

class Y : public X {
private:
    int j;
public:
    Y(int i, int j) : X(i), j(j) {}
    int getJ() {
        return j;
    }
};

class A {
protected:
    X* x;
public:
    A(X* a) : x(a) {}
    X* get() {
        return x;
    }
};

class B : public A {
public:
    B(Y* y) : A(y) {}
private:
    //I could create a new function for each class like class B
    Y* getY() {
        return (Y*)x;
    }
public:
    void doStuff() {
        Y* y = getY();
        y->getJ();
        std::cout << "J: " << y->getJ() << cout::endl;
    }
};

从主要提取:

X* x = new X(5);
Y* y = new Y(5,6);
B b(y);
b.doStuff();

我想到的一个替代方案是,当我构造类BI时,可以初始化一个Y类型变量的指针,该指针指向与在X中设置的位置相同的位置。只要我的指针是const,我认为应该是从两个引用中得到保护,指向不同的东西。

欢迎任何想法。

感谢。

2 个答案:

答案 0 :(得分:1)

好吧,我要做的第一件事是打破A和B之间的继承关系。你说他们有一个共同的接口,所以从定义这个接口开始:

class ILibraryWrapper {
public:
    virtual X * get() = 0;
};

我假设A和B共享很多代码(因此是继承关系),所以接下来定义一个模板类来实现接口并定义公共位:

template <class T> class LibraryWrapper : public ILibraryWrapper {
protected:
    T * pointer;

public:
    LibraryWrapper( T * value ) : pointer( value ) {}

    virtual X * get() override { return static_cast<X *>( this->pointer ); }
};

最后,像这样定义A和B:

class A : public LibraryWrapper<X> {
public:
    A( X * value ) : LibraryWrapper( value ) {}
};

class B : public LibraryWrapper<Y> {
public:
    B( Y * value ) : LibraryWrapper( value ) {}

    void doStuff() {
        std::cout << "J: " << this->pointer->getJ() << cout::endl;
    }
};

几乎所有代码都应该处理ILibraryWrapper指针或引用。如果某些代码绝对必须知道包装对象的具体类型,那么您可以进行动态转换:

auto wrapper = dynamic_cast<LibraryWrapper<Y> *>( object );
if( wrapper != nullptr ) {
    // ...
}

但一般来说,最好在ILibraryWrapper界面中提供所有需要的功能。

答案 1 :(得分:0)

只要Y来自X,而B来自A,那么这很容易。

只要返回类型是多态的,虚函数就可以因返回类型而不同。在A:

中实现以下内容
virtual X* Get() const { return x; }

以下B:

virtual Y* Get() const { return static_cast< Y* >( A::Get() ); }