假设我有两个c++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
有人可能认为n被设为2。
结果是n被设为1。为什么?
解决这个问题的一个方法是使用工厂方法来创建对象。
为你的类层次结构定义一个公共基类,其中包含一个虚拟方法afterConstruction():
class Object
{
public:
virtual void afterConstruction() {}
// ...
};
定义一个工厂方法:
template< class C >
C* factoryNew()
{
C* pObject = new C();
pObject->afterConstruction();
return pObject;
}
像这样使用它:
class MyClass : public Object
{
public:
virtual void afterConstruction()
{
// do something.
}
// ...
};
MyClass* pMyObject = factoryNew();
正如已经指出的那样,对象是在构造时创建的。在构造基对象时,派生对象还不存在,因此虚函数重写不能工作。
然而,如果你的getter返回常量,这可以用多态getter来解决,多态getter使用静态多态性而不是虚函数,或者可以在静态成员函数中表示。本例使用CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。
template<typename DerivedClass>
class Base
{
public:
inline Base() :
foo(DerivedClass::getFoo())
{}
inline int fooSq() {
return foo * foo;
}
const int foo;
};
class A : public Base<A>
{
public:
inline static int getFoo() { return 1; }
};
class B : public Base<B>
{
public:
inline static int getFoo() { return 2; }
};
class C : public Base<C>
{
public:
inline static int getFoo() { return 3; }
};
int main()
{
A a;
B b;
C c;
std::cout << a.fooSq() << ", " << b.fooSq() << ", " << c.fooSq() << std::endl;
return 0;
}
通过使用静态多态性,基类知道在编译时提供信息时调用哪个类的getter。