C++正在更改子类中拥有的对象类型



我们有四个类:A、B、X和Y。B从A继承,Y从X继承。A的每个实例都创建一个类型为X的所属对象。一些伪代码:

class A {
protected:
X * OwnedObject;
}
class B : public A {
B();
void BFunction();
};
B::B() {
OwnedObject = new Y();
}
B::BFunction() {
OwnedObject -> YFunction(); //error, class A has no member named 'YFunction()'
}
class X {};
class Y : public X {
void YFunction(); //this function is new, it is not in X
};

B、 当然,继承了指向X的指针。如果我们希望B创建(及其指向的OwnedObject指针)子类Y的对象,而不是父类X的对象,该怎么办?解决这个问题最正确的方法是什么?

编辑:很抱歉,如果我不清楚,我添加了更多的伪代码,以更具体地说明我遇到的问题和我想做什么。感谢迄今为止的输入!

我可以想到两种不同的方法。

在第一个例子中,我假设类X可以知道其子类可能更改/实现的函数,但它(X)本身并不知道确切的实现。在这种情况下,我在X中有一个virtual函数,根据是否有可能从X实例化,有两个实现:

// this X can not be instantiated
class X{
public:
virtual void f() = 0;
}
class Y : public X{
public:
virtual void f() { stuff to do; }
}

或者:

// this X can be instantiated
class X{
public:
virtual void f() { };
}
class Y : public X{
public:
virtual void f() { stuff to do; }
}

或者在另一个场景中,我假设因为B是从Y实例化的,所以它知道它是从Y实例化的,因此它可以安全地将其转换为Y,无论何时它想使用它:

B::BFunction() {
static_cast<Y*>(OwnedObject) -> YFunction(); 
}

或者,如果你想安全起见:

B::BFunction() {
if (dynamic_cast<Y*>(OwnedObject) != null)
static_cast<Y*>(OwnedObject) -> YFunction();
}

有点像这样吗?

class A {
protected:
A(X *x) : OwnedObject(x) {
// code...
}
X * OwnedObject;
}
class B : public A {
public:
B() : A(new Y()) {
// code...
}
};

我刚刚向A添加了从任何子类注入X对象的可能性

adrin的static_cast解决方案可能是您能做的最简单的事情。您只需要确保OwndedObject始终是Y的实例(而不是X或它的另一个子类)。

您可以在运行时检查(请参阅adrin的答案中的dynamic_cast,但使用dynamic_cast的结果,而不是添加另一个static_cast)。

B::BFunction() {
if (Y* y = dynamic_cast<Y*>(OwnedObject))
y->YFunction();
}

或者,您可以声明指针const(指针,而不是指针对象!星号后面的"const"关键字),并在构造函数中初始化它(ichramm的答案)。然后,您只需要查看A和B的构造函数,就可以推断您的static_cast是安全的。

您可以通过模板配置OwnedObject的类型。受此启发:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern.

或者,与其将指针存储在基类中,不如创建一个虚拟成员函数来提供对它的读取访问:

class A_interface {
public:
virtual X* getX() = 0;
};
class A: public A_interface {
X* OwnedObject;
public:
virtual X* getX() {return OwnedObject;}
};
// B is no subclass of A anymore, because you don't want that X* member.
class B: public A_interface {
Y* OwnedObject;
public:
virtual X* getX() {return OwnedObject;}
};

根据设计,你不能在a_interface中有一个setX(X*)虚拟成员函数,因为你不能在B中实现它。http://en.wikipedia.org/wiki/Covariance_and_contravariance_(计算机科学)

最新更新